@tamagui/select 1.0.1-beta.113 → 1.0.1-beta.114

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 (109) hide show
  1. package/dist/cjs/Select.js +50 -558
  2. package/dist/cjs/Select.js.map +2 -2
  3. package/dist/cjs/SelectContent.js +53 -0
  4. package/dist/cjs/SelectContent.js.map +7 -0
  5. package/dist/cjs/SelectContent.native.js +31 -0
  6. package/dist/cjs/SelectContent.native.js.map +7 -0
  7. package/dist/cjs/SelectImpl.js +393 -0
  8. package/dist/cjs/SelectImpl.js.map +7 -0
  9. package/dist/cjs/SelectScrollButton.js +128 -0
  10. package/dist/cjs/SelectScrollButton.js.map +7 -0
  11. package/dist/cjs/SelectScrollButton.native.js +32 -0
  12. package/dist/cjs/SelectScrollButton.native.js.map +7 -0
  13. package/dist/cjs/SelectViewport.js +96 -0
  14. package/dist/cjs/SelectViewport.js.map +7 -0
  15. package/dist/cjs/SelectViewport.native.js +43 -0
  16. package/dist/cjs/SelectViewport.native.js.map +7 -0
  17. package/dist/cjs/constants.js +47 -0
  18. package/dist/cjs/constants.js.map +7 -0
  19. package/dist/cjs/context.js +38 -0
  20. package/dist/cjs/context.js.map +7 -0
  21. package/dist/cjs/index.js +19 -0
  22. package/dist/cjs/index.js.map +2 -2
  23. package/dist/cjs/types.js +17 -0
  24. package/dist/cjs/types.js.map +7 -0
  25. package/dist/esm/Select.js +33 -565
  26. package/dist/esm/Select.js.map +2 -2
  27. package/dist/esm/SelectContent.js +26 -0
  28. package/dist/esm/SelectContent.js.map +7 -0
  29. package/dist/esm/SelectContent.native.js +7 -0
  30. package/dist/esm/SelectContent.native.js.map +7 -0
  31. package/dist/esm/SelectImpl.js +378 -0
  32. package/dist/esm/SelectImpl.js.map +7 -0
  33. package/dist/esm/SelectScrollButton.js +100 -0
  34. package/dist/esm/SelectScrollButton.js.map +7 -0
  35. package/dist/esm/SelectScrollButton.native.js +7 -0
  36. package/dist/esm/SelectScrollButton.native.js.map +7 -0
  37. package/dist/esm/SelectViewport.js +68 -0
  38. package/dist/esm/SelectViewport.js.map +7 -0
  39. package/dist/esm/SelectViewport.native.js +16 -0
  40. package/dist/esm/SelectViewport.native.js.map +7 -0
  41. package/dist/esm/constants.js +17 -0
  42. package/dist/esm/constants.js.map +7 -0
  43. package/dist/esm/context.js +11 -0
  44. package/dist/esm/context.js.map +7 -0
  45. package/dist/esm/index.js +13 -0
  46. package/dist/esm/index.js.map +2 -2
  47. package/dist/esm/types.js +1 -0
  48. package/dist/esm/types.js.map +7 -0
  49. package/dist/jsx/Select.js +32 -515
  50. package/dist/jsx/Select.js.map +2 -2
  51. package/dist/jsx/SelectContent.js +19 -0
  52. package/dist/jsx/SelectContent.js.map +7 -0
  53. package/dist/jsx/SelectContent.native.js +7 -0
  54. package/dist/jsx/SelectContent.native.js.map +7 -0
  55. package/dist/jsx/SelectImpl.js +366 -0
  56. package/dist/jsx/SelectImpl.js.map +7 -0
  57. package/dist/jsx/SelectScrollButton.js +78 -0
  58. package/dist/jsx/SelectScrollButton.js.map +7 -0
  59. package/dist/jsx/SelectScrollButton.native.js +7 -0
  60. package/dist/jsx/SelectScrollButton.native.js.map +7 -0
  61. package/dist/jsx/SelectViewport.js +57 -0
  62. package/dist/jsx/SelectViewport.js.map +7 -0
  63. package/dist/jsx/SelectViewport.native.js +14 -0
  64. package/dist/jsx/SelectViewport.native.js.map +7 -0
  65. package/dist/jsx/constants.js +17 -0
  66. package/dist/jsx/constants.js.map +7 -0
  67. package/dist/jsx/context.js +11 -0
  68. package/dist/jsx/context.js.map +7 -0
  69. package/dist/jsx/index.js +13 -0
  70. package/dist/jsx/index.js.map +2 -2
  71. package/dist/jsx/types.js +1 -0
  72. package/dist/jsx/types.js.map +7 -0
  73. package/package.json +12 -12
  74. package/src/Select.tsx +57 -881
  75. package/src/SelectContent.native.tsx +5 -0
  76. package/src/SelectContent.tsx +34 -0
  77. package/src/SelectImpl.tsx +511 -0
  78. package/src/SelectScrollButton.native.tsx +7 -0
  79. package/src/SelectScrollButton.tsx +150 -0
  80. package/src/SelectViewport.native.tsx +17 -0
  81. package/src/SelectViewport.tsx +86 -0
  82. package/src/constants.tsx +7 -0
  83. package/src/context.tsx +9 -0
  84. package/src/index.tsx +7 -0
  85. package/src/types.tsx +83 -0
  86. package/types/Select.d.ts +140 -298
  87. package/types/Select.d.ts.map +1 -1
  88. package/types/SelectContent.d.ts +4 -0
  89. package/types/SelectContent.d.ts.map +1 -0
  90. package/types/SelectContent.native.d.ts +4 -0
  91. package/types/SelectContent.native.d.ts.map +1 -0
  92. package/types/SelectImpl.d.ts +9 -0
  93. package/types/SelectImpl.d.ts.map +1 -0
  94. package/types/SelectScrollButton.d.ts +6 -0
  95. package/types/SelectScrollButton.d.ts.map +1 -0
  96. package/types/SelectScrollButton.native.d.ts +4 -0
  97. package/types/SelectScrollButton.native.d.ts.map +1 -0
  98. package/types/SelectViewport.d.ts +127 -0
  99. package/types/SelectViewport.d.ts.map +1 -0
  100. package/types/SelectViewport.native.d.ts +54 -0
  101. package/types/SelectViewport.native.d.ts.map +1 -0
  102. package/types/constants.d.ts +8 -0
  103. package/types/constants.d.ts.map +1 -0
  104. package/types/context.d.ts +17 -0
  105. package/types/context.d.ts.map +1 -0
  106. package/types/index.d.ts +2 -0
  107. package/types/index.d.ts.map +1 -1
  108. package/types/types.d.ts +74 -0
  109. package/types/types.d.ts.map +1 -0
@@ -1,59 +1,28 @@
1
- import {
2
- FloatingFocusManager,
3
- FloatingOverlay,
4
- FloatingPortal,
5
- autoUpdate,
6
- detectOverflow,
7
- flip,
8
- offset,
9
- size,
10
- useClick,
11
- useDismiss,
12
- useFloating,
13
- useInteractions,
14
- useListNavigation,
15
- useRole,
16
- useTypeahead
17
- } from "@floating-ui/react-dom-interactions";
18
- import { usePrevious } from "@radix-ui/react-use-previous";
19
1
  import { useComposedRefs } from "@tamagui/compose-refs";
20
2
  import { isWeb, useMedia } from "@tamagui/core";
21
- import {
22
- Theme,
23
- styled,
24
- useGet,
25
- useIsomorphicLayoutEffect,
26
- useThemeName,
27
- withStaticProperties
28
- } from "@tamagui/core";
3
+ import { styled, useGet, useIsomorphicLayoutEffect, withStaticProperties } from "@tamagui/core";
29
4
  import { useId } from "@tamagui/core";
30
- import { createContextScope } from "@tamagui/create-context";
31
5
  import { ListItem } from "@tamagui/list-item";
32
- import { PortalHost, PortalItem } from "@tamagui/portal";
6
+ import { PortalHost } from "@tamagui/portal";
33
7
  import { Separator } from "@tamagui/separator";
34
8
  import { Sheet, SheetController } from "@tamagui/sheet";
35
- import { ThemeableStack, XStack, YStack } from "@tamagui/stacks";
9
+ import { XStack, YStack } from "@tamagui/stacks";
36
10
  import { Paragraph } from "@tamagui/text";
37
11
  import { useControllableState } from "@tamagui/use-controllable-state";
38
12
  import * as React from "react";
39
13
  import * as ReactDOM from "react-dom";
40
- const SELECT_NAME = "Select";
41
- const WINDOW_PADDING = 8;
42
- const SCROLL_ARROW_VELOCITY = 8;
43
- const SCROLL_ARROW_THRESHOLD = 8;
44
- const MIN_HEIGHT = 80;
45
- const FALLBACK_THRESHOLD = 16;
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";
46
20
  const userAgent = typeof navigator !== "undefined" && navigator.userAgent || "";
47
21
  const isFirefox = userAgent.toLowerCase().includes("firefox");
48
- if (isFirefox) {
49
- document.body.classList.add("firefox");
50
- }
51
22
  function getVisualOffsetTop() {
52
23
  var _a;
53
24
  return !/^((?!chrome|android).)*safari/i.test(userAgent) ? (_a = visualViewport == null ? void 0 : visualViewport.offsetTop) != null ? _a : 0 : 0;
54
25
  }
55
- const [createSelectContext, createSelectScope] = createContextScope(SELECT_NAME);
56
- const [SelectProvider, useSelectContext] = createSelectContext(SELECT_NAME);
57
26
  const TRIGGER_NAME = "SelectTrigger";
58
27
  const SelectTrigger = React.forwardRef((props, forwardedRef) => {
59
28
  const {
@@ -76,14 +45,15 @@ const SelectValueFrame = styled(Paragraph, {
76
45
  name: VALUE_NAME,
77
46
  selectable: false
78
47
  });
79
- const SelectValue = SelectValueFrame.extractable(React.forwardRef(({ __scopeSelect, children, placeholder }, forwardedRef) => {
48
+ const SelectValue = SelectValueFrame.extractable(React.forwardRef(({ __scopeSelect, children: childrenProp, placeholder }, forwardedRef) => {
80
49
  const context = useSelectContext(VALUE_NAME, __scopeSelect);
81
50
  const { onValueNodeHasChildrenChange } = context;
82
- const hasChildren = children !== void 0;
51
+ const hasChildren = childrenProp !== void 0;
83
52
  const composedRefs = useComposedRefs(forwardedRef, context.onValueNodeChange);
84
53
  React.useLayoutEffect(() => {
85
54
  onValueNodeHasChildrenChange(hasChildren);
86
55
  }, [onValueNodeHasChildrenChange, hasChildren]);
56
+ const children = childrenProp != null ? childrenProp : context.selectedItem;
87
57
  return <SelectValueFrame size={context.size} ref={composedRefs} pointerEvents="none">{context.value === void 0 && placeholder !== void 0 ? placeholder : children}</SelectValueFrame>;
88
58
  }));
89
59
  SelectValue.displayName = VALUE_NAME;
@@ -92,61 +62,6 @@ const SelectIcon = styled(XStack, {
92
62
  "aria-hidden": true,
93
63
  children: <Paragraph>{"\u25BC"}</Paragraph>
94
64
  });
95
- const CONTENT_NAME = "SelectContent";
96
- const SelectContent = ({ children, __scopeSelect }) => {
97
- const context = useSelectContext(CONTENT_NAME, __scopeSelect);
98
- const themeName = useThemeName();
99
- const showSheet = useShowSelectSheet(context);
100
- const contents = <Theme name={themeName}>{children}</Theme>;
101
- if (showSheet && context.open) {
102
- return contents;
103
- }
104
- return <FloatingPortal>{context.open ? <FloatingOverlay lockScroll>{contents}</FloatingOverlay> : <div style={{ display: "none" }}>{contents}</div>}</FloatingPortal>;
105
- };
106
- const VIEWPORT_NAME = "SelectViewport";
107
- const SelectViewportFrame = styled(ThemeableStack, {
108
- name: VIEWPORT_NAME,
109
- backgroundColor: "$background",
110
- elevate: true,
111
- bordered: true,
112
- overflow: "scroll",
113
- userSelect: "none",
114
- variants: {
115
- size: {
116
- "...size": (val, { tokens }) => {
117
- var _a;
118
- return {
119
- borderRadius: (_a = tokens.radius[val]) != null ? _a : val
120
- };
121
- }
122
- }
123
- },
124
- defaultVariants: {
125
- size: "$2"
126
- }
127
- });
128
- const SelectViewport = React.forwardRef((props, forwardedRef) => {
129
- var _a, _b;
130
- const { __scopeSelect, children, ...viewportProps } = props;
131
- const context = useSelectContext(VIEWPORT_NAME, __scopeSelect);
132
- const { style, ...floatingProps } = (_b = (_a = context.interactions) == null ? void 0 : _a.getFloatingProps()) != null ? _b : {};
133
- const breakpointActive = useSelectBreakpointActive(context.sheetBreakpoint);
134
- if (breakpointActive || !isWeb) {
135
- return <PortalItem hostName={`${context.scopeKey}SheetContents`}>{children}</PortalItem>;
136
- }
137
- if (!context.floatingContext) {
138
- return null;
139
- }
140
- delete style["scrollbarWidth"];
141
- delete style["listStyleType"];
142
- return <>
143
- <style dangerouslySetInnerHTML={{
144
- __html: `[data-tamagui-select-viewport]{scrollbar-width:none;-ms-overflow-style:none;-webkit-overflow-scrolling:touch;}[data-tamagui-select-viewport]::-webkit-scrollbar{display:none}`
145
- }} />
146
- <FloatingFocusManager context={context.floatingContext} preventTabbing><SelectViewportFrame size={context.size} data-tamagui-select-viewport="" role="presentation" {...viewportProps} ref={forwardedRef} {...floatingProps} {...style}>{children}</SelectViewportFrame></FloatingFocusManager>
147
- </>;
148
- });
149
- SelectViewport.displayName = VIEWPORT_NAME;
150
65
  const ITEM_NAME = "SelectItem";
151
66
  const [SelectItemContextProvider, useSelectItemContext] = createSelectContext(ITEM_NAME);
152
67
  const SelectItem = React.forwardRef((props, forwardedRef) => {
@@ -176,6 +91,8 @@ const SelectItem = React.forwardRef((props, forwardedRef) => {
176
91
  dataRef
177
92
  } = context;
178
93
  const composedRefs = useComposedRefs(forwardedRef, (node) => {
94
+ if (!isWeb)
95
+ return;
179
96
  if (node instanceof HTMLElement) {
180
97
  if (listRef) {
181
98
  listRef.current[index] = node;
@@ -238,9 +155,18 @@ const SelectItemText = React.forwardRef((props, forwardedRef) => {
238
155
  const itemContext = useSelectItemContext(ITEM_TEXT_NAME, __scopeSelect);
239
156
  const ref = React.useRef(null);
240
157
  const composedRefs = useComposedRefs(forwardedRef, ref, itemContext.onItemTextChange);
158
+ const isSelected = itemContext.isSelected && context.valueNode && !context.valueNodeHasChildren;
159
+ const contents = <SelectItemTextFrame className={className} size={context.size} id={itemContext.textId} {...itemTextProps} ref={composedRefs} />;
160
+ if (!isWeb) {
161
+ React.useEffect(() => {
162
+ if (isSelected) {
163
+ context.setSelectedItem(contents);
164
+ }
165
+ }, [isSelected]);
166
+ }
241
167
  return <>
242
- <SelectItemTextFrame className={className} size={context.size} id={itemContext.textId} {...itemTextProps} ref={composedRefs} />
243
- {itemContext.isSelected && context.valueNode && !context.valueNodeHasChildren ? ReactDOM.createPortal(itemTextProps.children, context.valueNode) : null}
168
+ {contents}
169
+ {isWeb && isSelected ? ReactDOM.createPortal(itemTextProps.children, context.valueNode) : null}
244
170
  </>;
245
171
  });
246
172
  SelectItemText.displayName = ITEM_TEXT_NAME;
@@ -274,73 +200,6 @@ const SelectLabel = React.forwardRef((props, forwardedRef) => {
274
200
  return <ListItem componentName={LABEL_NAME} fontWeight="800" id={groupContext.id} size={context.size} {...labelProps} ref={forwardedRef} />;
275
201
  });
276
202
  SelectLabel.displayName = LABEL_NAME;
277
- const SCROLL_UP_BUTTON_NAME = "SelectScrollUpButton";
278
- const SelectScrollUpButton = React.forwardRef((props, forwardedRef) => {
279
- return <SelectScrollButtonImpl componentName={SCROLL_UP_BUTTON_NAME} {...props} dir="up" ref={forwardedRef} />;
280
- });
281
- SelectScrollUpButton.displayName = SCROLL_UP_BUTTON_NAME;
282
- const SCROLL_DOWN_BUTTON_NAME = "SelectScrollDownButton";
283
- const SelectScrollDownButton = React.forwardRef((props, forwardedRef) => {
284
- return <SelectScrollButtonImpl componentName={SCROLL_DOWN_BUTTON_NAME} {...props} dir="down" ref={forwardedRef} />;
285
- });
286
- SelectScrollDownButton.displayName = SCROLL_DOWN_BUTTON_NAME;
287
- const SelectScrollButtonImpl = React.memo(React.forwardRef((props, forwardedRef) => {
288
- var _a, _b;
289
- const { __scopeSelect, dir, componentName, ...scrollIndicatorProps } = props;
290
- const { floatingRef, increaseHeight, forceUpdate, ...context } = useSelectContext(componentName, __scopeSelect);
291
- const intervalRef = React.useRef();
292
- const loopingRef = React.useRef(false);
293
- const isVisible = context[dir === "down" ? "canScrollDown" : "canScrollUp"];
294
- const { x, y, reference, floating, strategy, update, refs } = useFloating({
295
- strategy: "fixed",
296
- placement: dir === "up" ? "top" : "bottom",
297
- middleware: [offset(({ rects }) => -rects.floating.height)]
298
- });
299
- const composedRefs = useComposedRefs(forwardedRef, floating);
300
- React.useLayoutEffect(() => {
301
- if (!floatingRef)
302
- return;
303
- reference(floatingRef.current);
304
- }, [reference, floatingRef == null ? void 0 : floatingRef.current]);
305
- React.useEffect(() => {
306
- if (!refs.reference.current || !refs.floating.current || !isVisible) {
307
- return;
308
- }
309
- const cleanup = autoUpdate(refs.reference.current, refs.floating.current, update, {
310
- animationFrame: true
311
- });
312
- return () => {
313
- clearInterval(intervalRef.current);
314
- loopingRef.current = false;
315
- cleanup();
316
- };
317
- }, [isVisible, update, refs.floating, refs.reference]);
318
- if (!isVisible) {
319
- return null;
320
- }
321
- const handleScrollArrowChange = () => {
322
- if (!floatingRef)
323
- return;
324
- const floating2 = floatingRef.current;
325
- const isUp = dir === "up";
326
- if (floating2) {
327
- const value = isUp ? -SCROLL_ARROW_VELOCITY : SCROLL_ARROW_VELOCITY;
328
- const multi = isUp && floating2.scrollTop <= SCROLL_ARROW_THRESHOLD * 2 || !isUp && floating2.scrollTop >= floating2.scrollHeight - floating2.clientHeight - SCROLL_ARROW_THRESHOLD * 2 ? 2 : 1;
329
- floating2.scrollTop += multi * (isUp ? -SCROLL_ARROW_VELOCITY : SCROLL_ARROW_VELOCITY);
330
- increaseHeight == null ? void 0 : increaseHeight(floating2, multi === 2 ? value * 2 : value);
331
- forceUpdate();
332
- }
333
- };
334
- return <YStack ref={composedRefs} componentName={componentName} aria-hidden {...scrollIndicatorProps} zIndex={1e3} position={strategy} left={x || 0} top={y || 0} width={`calc(${((_b = (_a = floatingRef == null ? void 0 : floatingRef.current) == null ? void 0 : _a.offsetWidth) != null ? _b : 0) - 2}px)`} onPointerMove={() => {
335
- if (!loopingRef.current) {
336
- intervalRef.current = setInterval(handleScrollArrowChange, 1e3 / 60);
337
- loopingRef.current = true;
338
- }
339
- }} onPointerLeave={() => {
340
- loopingRef.current = false;
341
- clearInterval(intervalRef.current);
342
- }} />;
343
- }));
344
203
  const SelectSeparator = styled(Separator, {
345
204
  name: "SelectSeparator"
346
205
  });
@@ -369,350 +228,6 @@ const SelectSheetContents = ({ __scopeSelect }) => {
369
228
  return <PortalHost name={`${context.scopeKey}SheetContents`} />;
370
229
  };
371
230
  SelectSheetContents.displayName = SHEET_CONTENTS_NAME;
372
- const SelectInlineImpl = (props) => {
373
- const {
374
- __scopeSelect,
375
- children,
376
- open = false,
377
- activeIndexRef,
378
- selectedIndexRef,
379
- listContentRef
380
- } = props;
381
- const selectContext = useSelectContext("SelectSheetImpl", __scopeSelect);
382
- const { setActiveIndex, setOpen, setSelectedIndex, selectedIndex, activeIndex, forceUpdate } = selectContext;
383
- const [showArrows, setShowArrows] = React.useState(false);
384
- const [scrollTop, setScrollTop] = React.useState(0);
385
- const prevActiveIndex = usePrevious(activeIndex);
386
- const listItemsRef = React.useRef([]);
387
- const [controlledScrolling, setControlledScrolling] = React.useState(false);
388
- const [middlewareType, setMiddlewareType] = React.useState("align");
389
- React.useEffect(() => {
390
- const frame = requestAnimationFrame(() => {
391
- setShowArrows(open);
392
- if (!open) {
393
- setScrollTop(0);
394
- setMiddlewareType("align");
395
- setActiveIndex(null);
396
- setControlledScrolling(false);
397
- }
398
- });
399
- return () => {
400
- cancelAnimationFrame(frame);
401
- };
402
- }, [open, setActiveIndex]);
403
- function getFloatingPadding(floating2) {
404
- var _a;
405
- if (!floating2) {
406
- return 0;
407
- }
408
- return Number((_a = getComputedStyle(floating2).paddingLeft) == null ? void 0 : _a.replace("px", ""));
409
- }
410
- const { x, y, reference, floating, strategy, context, refs, middlewareData, update } = useFloating({
411
- open,
412
- onOpenChange: setOpen,
413
- placement: "bottom",
414
- middleware: middlewareType === "align" ? [
415
- offset(({ rects }) => {
416
- var _a;
417
- const index = (_a = activeIndexRef.current) != null ? _a : selectedIndexRef.current;
418
- if (index == null) {
419
- return 0;
420
- }
421
- const item = listItemsRef.current[index];
422
- if (item == null) {
423
- return 0;
424
- }
425
- const offsetTop = item.offsetTop;
426
- const itemHeight = item.offsetHeight;
427
- const height = rects.reference.height;
428
- return -offsetTop - height - (itemHeight - height) / 2;
429
- }),
430
- {
431
- name: "size",
432
- async fn(args) {
433
- var _a;
434
- const {
435
- elements: { floating: floating2 },
436
- rects: { reference: reference2 },
437
- middlewareData: middlewareData2
438
- } = args;
439
- const overflow = await detectOverflow(args, {
440
- padding: WINDOW_PADDING
441
- });
442
- const top = Math.max(0, overflow.top);
443
- const bottom = Math.max(0, overflow.bottom);
444
- const nextY = args.y + top;
445
- if ((_a = middlewareData2.size) == null ? void 0 : _a.skip) {
446
- return {
447
- y: nextY,
448
- data: {
449
- y: middlewareData2.size.y
450
- }
451
- };
452
- }
453
- Object.assign(floating2.style, {
454
- maxHeight: `${floating2.scrollHeight - Math.abs(top + bottom)}px`,
455
- minWidth: `${reference2.width + getFloatingPadding(floating2) * 2}px`
456
- });
457
- return {
458
- y: nextY,
459
- data: {
460
- y: top,
461
- skip: true
462
- },
463
- reset: {
464
- rects: true
465
- }
466
- };
467
- }
468
- }
469
- ] : [
470
- offset(5),
471
- flip(),
472
- size({
473
- apply({ rects, availableHeight, elements }) {
474
- Object.assign(elements.floating.style, {
475
- width: `${rects.reference.width}px`,
476
- maxHeight: `${availableHeight}px`
477
- });
478
- },
479
- padding: WINDOW_PADDING
480
- })
481
- ]
482
- });
483
- const floatingRef = refs.floating;
484
- const showUpArrow = showArrows && scrollTop > SCROLL_ARROW_THRESHOLD;
485
- const showDownArrow = showArrows && floatingRef.current && scrollTop < floatingRef.current.scrollHeight - floatingRef.current.clientHeight - SCROLL_ARROW_THRESHOLD;
486
- const interactions = useInteractions([
487
- useClick(context, { pointerDown: true }),
488
- useRole(context, { role: "listbox" }),
489
- useDismiss(context),
490
- useListNavigation(context, {
491
- listRef: listItemsRef,
492
- activeIndex,
493
- selectedIndex,
494
- onNavigate: setActiveIndex
495
- }),
496
- useTypeahead(context, {
497
- listRef: listContentRef,
498
- onMatch: open ? setActiveIndex : setSelectedIndex,
499
- selectedIndex,
500
- activeIndex
501
- })
502
- ]);
503
- const increaseHeight = React.useCallback((floating2, amount = 0) => {
504
- var _a;
505
- if (middlewareType === "fallback") {
506
- return;
507
- }
508
- const currentMaxHeight = Number(floating2.style.maxHeight.replace("px", ""));
509
- const currentTop = Number(floating2.style.top.replace("px", ""));
510
- const rect = floating2.getBoundingClientRect();
511
- const rectTop = rect.top;
512
- const rectBottom = rect.bottom;
513
- const viewportHeight = (_a = visualViewport == null ? void 0 : visualViewport.height) != null ? _a : 0;
514
- const visualMaxHeight = viewportHeight - WINDOW_PADDING * 2;
515
- if (amount < 0 && selectedIndexRef.current != null && Math.round(rectBottom) < Math.round(viewportHeight + getVisualOffsetTop() - WINDOW_PADDING)) {
516
- floating2.style.maxHeight = `${Math.min(visualMaxHeight, currentMaxHeight - amount)}px`;
517
- }
518
- if (amount > 0 && Math.round(rectTop) > Math.round(WINDOW_PADDING - getVisualOffsetTop()) && floating2.scrollHeight > floating2.offsetHeight) {
519
- const nextTop = Math.max(WINDOW_PADDING + getVisualOffsetTop(), currentTop - amount);
520
- const nextMaxHeight = Math.min(visualMaxHeight, currentMaxHeight + amount);
521
- Object.assign(floating2.style, {
522
- maxHeight: `${nextMaxHeight}px`,
523
- top: `${nextTop}px`
524
- });
525
- if (nextTop - WINDOW_PADDING > getVisualOffsetTop()) {
526
- floating2.scrollTop -= nextMaxHeight - currentMaxHeight + getFloatingPadding(floating2);
527
- }
528
- return currentTop - nextTop;
529
- }
530
- }, [middlewareType, selectedIndexRef]);
531
- const touchPageYRef = React.useRef(null);
532
- const handleWheel = React.useCallback((event) => {
533
- var _a, _b, _c;
534
- const pinching = event.ctrlKey;
535
- const currentTarget = event.currentTarget;
536
- function isWheelEvent(event2) {
537
- return typeof event2.deltaY === "number";
538
- }
539
- function isTouchEvent(event2) {
540
- return event2.touches != null;
541
- }
542
- if (Math.abs(((_a = currentTarget == null ? void 0 : currentTarget.offsetHeight) != null ? _a : 0) - (((_b = visualViewport == null ? void 0 : visualViewport.height) != null ? _b : 0) - WINDOW_PADDING * 2)) > 1 && !pinching) {
543
- event.preventDefault();
544
- } else if (isWheelEvent(event) && isFirefox) {
545
- currentTarget.scrollTop += event.deltaY;
546
- }
547
- if (!pinching) {
548
- let delta = 5;
549
- if (isTouchEvent(event)) {
550
- const currentPageY = touchPageYRef.current;
551
- const pageY = (_c = event.touches[0]) == null ? void 0 : _c.pageY;
552
- if (pageY != null) {
553
- touchPageYRef.current = pageY;
554
- if (currentPageY != null) {
555
- delta = currentPageY - pageY;
556
- }
557
- }
558
- }
559
- increaseHeight(currentTarget, isWheelEvent(event) ? event.deltaY : delta);
560
- setScrollTop(currentTarget.scrollTop);
561
- forceUpdate();
562
- }
563
- }, [forceUpdate, increaseHeight]);
564
- React.useEffect(() => {
565
- function onTouchEnd() {
566
- touchPageYRef.current = null;
567
- }
568
- const floating2 = floatingRef.current;
569
- if (open && floating2 && middlewareType === "align") {
570
- floating2.addEventListener("wheel", handleWheel);
571
- floating2.addEventListener("touchmove", handleWheel);
572
- floating2.addEventListener("touchend", onTouchEnd, { passive: true });
573
- return () => {
574
- floating2.removeEventListener("wheel", handleWheel);
575
- floating2.removeEventListener("touchmove", handleWheel);
576
- floating2.removeEventListener("touchend", onTouchEnd);
577
- };
578
- }
579
- }, [open, floatingRef, handleWheel, middlewareType]);
580
- React.useEffect(() => {
581
- window.addEventListener("resize", update);
582
- return () => {
583
- window.removeEventListener("resize", update);
584
- };
585
- }, [update]);
586
- React.useLayoutEffect(() => {
587
- var _a, _b, _c;
588
- const floating2 = floatingRef.current;
589
- if (open && controlledScrolling && floating2) {
590
- const item = activeIndex != null ? listItemsRef.current[activeIndex] : selectedIndex != null ? listItemsRef.current[selectedIndex] : null;
591
- if (item && prevActiveIndex != null) {
592
- const itemHeight = (_b = (_a = listItemsRef.current[prevActiveIndex]) == null ? void 0 : _a.offsetHeight) != null ? _b : 0;
593
- const floatingHeight = floating2.offsetHeight;
594
- const top = item.offsetTop;
595
- const bottom = top + itemHeight;
596
- if (top < floating2.scrollTop + 20) {
597
- const diff = floating2.scrollTop - top + 20;
598
- floating2.scrollTop -= diff;
599
- if (activeIndex != selectedIndex && activeIndex != null) {
600
- increaseHeight(floating2, -diff);
601
- }
602
- } else if (bottom > floatingHeight + floating2.scrollTop - 20) {
603
- const diff = bottom - floatingHeight - floating2.scrollTop + 20;
604
- floating2.scrollTop += diff;
605
- if (activeIndex != selectedIndex && activeIndex != null) {
606
- floating2.scrollTop -= (_c = increaseHeight(floating2, diff)) != null ? _c : 0;
607
- }
608
- }
609
- }
610
- }
611
- }, [
612
- open,
613
- controlledScrolling,
614
- prevActiveIndex,
615
- activeIndex,
616
- selectedIndex,
617
- floatingRef,
618
- increaseHeight
619
- ]);
620
- React.useLayoutEffect(() => {
621
- var _a, _b;
622
- const floating2 = refs.floating.current;
623
- const reference2 = refs.reference.current;
624
- if (open && floating2 && reference2 && floating2.offsetHeight < floating2.scrollHeight) {
625
- const referenceRect = reference2.getBoundingClientRect();
626
- if (middlewareType === "fallback") {
627
- const item = listItemsRef.current[selectedIndex];
628
- if (item) {
629
- floating2.scrollTop = item.offsetTop - floating2.clientHeight + referenceRect.height;
630
- }
631
- return;
632
- }
633
- floating2.scrollTop = (_a = middlewareData.size) == null ? void 0 : _a.y;
634
- const closeToBottom = ((_b = visualViewport == null ? void 0 : visualViewport.height) != null ? _b : 0) + getVisualOffsetTop() - referenceRect.bottom < FALLBACK_THRESHOLD;
635
- const closeToTop = referenceRect.top < FALLBACK_THRESHOLD;
636
- if (floating2.offsetHeight < MIN_HEIGHT || closeToTop || closeToBottom) {
637
- setMiddlewareType("fallback");
638
- }
639
- }
640
- }, [
641
- open,
642
- increaseHeight,
643
- selectedIndex,
644
- middlewareType,
645
- refs.floating,
646
- refs.reference,
647
- middlewareData
648
- ]);
649
- React.useLayoutEffect(() => {
650
- if (open && selectedIndex != null) {
651
- requestAnimationFrame(() => {
652
- var _a;
653
- (_a = listItemsRef.current[selectedIndex]) == null ? void 0 : _a.focus({ preventScroll: true });
654
- });
655
- }
656
- }, [listItemsRef, selectedIndex, open]);
657
- React.useEffect(() => {
658
- const frame = requestAnimationFrame(() => {
659
- setShowArrows(open);
660
- if (!open) {
661
- setScrollTop(0);
662
- setMiddlewareType("align");
663
- setActiveIndex(null);
664
- setControlledScrolling(false);
665
- }
666
- });
667
- return () => cancelAnimationFrame(frame);
668
- }, [open]);
669
- return <SelectProvider scope={__scopeSelect} {...selectContext} increaseHeight={increaseHeight} floatingRef={floatingRef} setValueAtIndex={(index, value) => {
670
- listContentRef.current[index] = value;
671
- }} interactions={{
672
- ...interactions,
673
- getReferenceProps() {
674
- return interactions.getReferenceProps({
675
- ref: reference,
676
- className: "SelectTrigger",
677
- onKeyDown(event) {
678
- if (event.key === "Enter" || event.key === " " && !context.dataRef.current.typing) {
679
- event.preventDefault();
680
- setOpen(true);
681
- }
682
- }
683
- });
684
- },
685
- getFloatingProps(props2) {
686
- return interactions.getFloatingProps({
687
- ref: floating,
688
- className: "Select",
689
- ...props2,
690
- style: {
691
- position: strategy,
692
- top: y != null ? y : "",
693
- left: x != null ? x : "",
694
- outline: 0,
695
- listStyleType: "none",
696
- scrollbarWidth: "none",
697
- userSelect: "none",
698
- ...props2 == null ? void 0 : props2.style
699
- },
700
- onPointerEnter() {
701
- setControlledScrolling(false);
702
- },
703
- onPointerMove() {
704
- setControlledScrolling(false);
705
- },
706
- onKeyDown() {
707
- setControlledScrolling(true);
708
- },
709
- onScroll(event) {
710
- setScrollTop(event.currentTarget.scrollTop);
711
- }
712
- });
713
- }
714
- }} floatingContext={context} activeIndex={activeIndex} canScrollDown={!!showDownArrow} canScrollUp={!!showUpArrow} controlledScrolling dataRef={context.dataRef} listRef={listItemsRef}>{children}</SelectProvider>;
715
- };
716
231
  const SelectSheetImpl = (props) => {
717
232
  return <>{props.children}</>;
718
233
  };
@@ -726,13 +241,14 @@ const Select = withStaticProperties((props) => {
726
241
  value: valueProp,
727
242
  defaultValue,
728
243
  onValueChange,
729
- size: sizeProp,
244
+ size: sizeProp = "$4",
730
245
  sheetBreakpoint = false,
731
246
  dir
732
247
  } = props;
733
248
  const isSheet = useSelectBreakpointActive(sheetBreakpoint);
734
249
  const SelectImpl = isSheet ? SelectSheetImpl : SelectInlineImpl;
735
250
  const forceUpdate = React.useReducer(() => ({}), {})[1];
251
+ const [selectedItem, setSelectedItem] = React.useState(null);
736
252
  const [open, setOpen] = useControllableState({
737
253
  prop: openProp,
738
254
  defaultProp: defaultOpen || false,
@@ -754,7 +270,7 @@ const Select = withStaticProperties((props) => {
754
270
  selectedIndexRef.current = selectedIndex;
755
271
  activeIndexRef.current = activeIndex;
756
272
  });
757
- return <SelectProvider dir={dir} size={sizeProp} forceUpdate={forceUpdate} valueNode={valueNode} onValueNodeChange={setValueNode} onValueNodeHasChildrenChange={setValueNodeHasChildren} valueNodeHasChildren={valueNodeHasChildren} scopeKey={__scopeSelect ? Object.keys(__scopeSelect)[0] : ""} sheetBreakpoint={sheetBreakpoint} scope={__scopeSelect} setValueAtIndex={(index, value2) => {
273
+ return <SelectProvider dir={dir} size={sizeProp} selectedItem={selectedItem} setSelectedItem={setSelectedItem} forceUpdate={forceUpdate} valueNode={valueNode} onValueNodeChange={setValueNode} onValueNodeHasChildrenChange={setValueNodeHasChildren} valueNodeHasChildren={valueNodeHasChildren} scopeKey={__scopeSelect ? Object.keys(__scopeSelect)[0] : ""} sheetBreakpoint={sheetBreakpoint} scope={__scopeSelect} setValueAtIndex={(index, value2) => {
758
274
  listContentRef.current[index] = value2;
759
275
  }} activeIndex={activeIndex} onChange={setValue} selectedIndex={selectedIndex} setActiveIndex={setActiveIndex} setOpen={setOpen} setSelectedIndex={setSelectedIndex} value={value} open={open}><SelectSheetController onChangeOpen={setOpen} __scopeSelect={__scopeSelect}><SelectImpl activeIndexRef={activeIndexRef} listContentRef={listContentRef} selectedIndexRef={selectedIndexRef} {...props} open={open} value={value}>{children}</SelectImpl></SelectSheetController></SelectProvider>;
760
276
  }, {
@@ -783,8 +299,9 @@ export {
783
299
  SelectSeparator,
784
300
  SelectSheetContents,
785
301
  SelectTrigger,
786
- SelectViewport,
787
- SelectViewportFrame,
788
- createSelectScope
302
+ getVisualOffsetTop,
303
+ isFirefox,
304
+ useSelectBreakpointActive,
305
+ useShowSelectSheet
789
306
  };
790
307
  //# sourceMappingURL=Select.js.map