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

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 +61 -567
  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 +1 -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 +44 -574
  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 +1 -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 +43 -516
  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 +1 -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 +69 -890
  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 +83 -241
  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,60 +1,39 @@
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";
27
+ const SelectTriggerFrame = styled(ListItem, {
28
+ componentName: TRIGGER_NAME,
29
+ backgrounded: true,
30
+ radiused: true,
31
+ hoverTheme: true,
32
+ pressTheme: true,
33
+ focusTheme: true,
34
+ focusable: false,
35
+ borderWidth: 1
36
+ });
58
37
  const SelectTrigger = React.forwardRef((props, forwardedRef) => {
59
38
  const {
60
39
  __scopeSelect,
@@ -64,7 +43,7 @@ const SelectTrigger = React.forwardRef((props, forwardedRef) => {
64
43
  } = props;
65
44
  const context = useSelectContext(TRIGGER_NAME, __scopeSelect);
66
45
  const labelledBy = ariaLabelledby;
67
- return <ListItem backgrounded radiused hoverTheme pressTheme focusTheme focusable={false} borderWidth={1} componentName={TRIGGER_NAME} 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} {...context.interactions ? context.interactions.getReferenceProps() : {
46
+ return <SelectTriggerFrame 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} {...context.interactions ? context.interactions.getReferenceProps() : {
68
47
  onPress() {
69
48
  context.setOpen(!context.open);
70
49
  }
@@ -76,14 +55,15 @@ const SelectValueFrame = styled(Paragraph, {
76
55
  name: VALUE_NAME,
77
56
  selectable: false
78
57
  });
79
- const SelectValue = SelectValueFrame.extractable(React.forwardRef(({ __scopeSelect, children, placeholder }, forwardedRef) => {
58
+ const SelectValue = SelectValueFrame.extractable(React.forwardRef(({ __scopeSelect, children: childrenProp, placeholder }, forwardedRef) => {
80
59
  const context = useSelectContext(VALUE_NAME, __scopeSelect);
81
60
  const { onValueNodeHasChildrenChange } = context;
82
- const hasChildren = children !== void 0;
61
+ const hasChildren = childrenProp !== void 0;
83
62
  const composedRefs = useComposedRefs(forwardedRef, context.onValueNodeChange);
84
63
  React.useLayoutEffect(() => {
85
64
  onValueNodeHasChildrenChange(hasChildren);
86
65
  }, [onValueNodeHasChildrenChange, hasChildren]);
66
+ const children = childrenProp != null ? childrenProp : context.selectedItem;
87
67
  return <SelectValueFrame size={context.size} ref={composedRefs} pointerEvents="none">{context.value === void 0 && placeholder !== void 0 ? placeholder : children}</SelectValueFrame>;
88
68
  }));
89
69
  SelectValue.displayName = VALUE_NAME;
@@ -92,61 +72,6 @@ const SelectIcon = styled(XStack, {
92
72
  "aria-hidden": true,
93
73
  children: <Paragraph>{"\u25BC"}</Paragraph>
94
74
  });
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
75
  const ITEM_NAME = "SelectItem";
151
76
  const [SelectItemContextProvider, useSelectItemContext] = createSelectContext(ITEM_NAME);
152
77
  const SelectItem = React.forwardRef((props, forwardedRef) => {
@@ -176,6 +101,8 @@ const SelectItem = React.forwardRef((props, forwardedRef) => {
176
101
  dataRef
177
102
  } = context;
178
103
  const composedRefs = useComposedRefs(forwardedRef, (node) => {
104
+ if (!isWeb)
105
+ return;
179
106
  if (node instanceof HTMLElement) {
180
107
  if (listRef) {
181
108
  listRef.current[index] = node;
@@ -238,9 +165,18 @@ const SelectItemText = React.forwardRef((props, forwardedRef) => {
238
165
  const itemContext = useSelectItemContext(ITEM_TEXT_NAME, __scopeSelect);
239
166
  const ref = React.useRef(null);
240
167
  const composedRefs = useComposedRefs(forwardedRef, ref, itemContext.onItemTextChange);
168
+ const isSelected = itemContext.isSelected && context.valueNode && !context.valueNodeHasChildren;
169
+ const contents = <SelectItemTextFrame className={className} size={context.size} id={itemContext.textId} {...itemTextProps} ref={composedRefs} />;
170
+ if (!isWeb) {
171
+ React.useEffect(() => {
172
+ if (isSelected) {
173
+ context.setSelectedItem(contents);
174
+ }
175
+ }, [isSelected]);
176
+ }
241
177
  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}
178
+ {contents}
179
+ {isWeb && isSelected ? ReactDOM.createPortal(itemTextProps.children, context.valueNode) : null}
244
180
  </>;
245
181
  });
246
182
  SelectItemText.displayName = ITEM_TEXT_NAME;
@@ -274,73 +210,6 @@ const SelectLabel = React.forwardRef((props, forwardedRef) => {
274
210
  return <ListItem componentName={LABEL_NAME} fontWeight="800" id={groupContext.id} size={context.size} {...labelProps} ref={forwardedRef} />;
275
211
  });
276
212
  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
213
  const SelectSeparator = styled(Separator, {
345
214
  name: "SelectSeparator"
346
215
  });
@@ -369,350 +238,6 @@ const SelectSheetContents = ({ __scopeSelect }) => {
369
238
  return <PortalHost name={`${context.scopeKey}SheetContents`} />;
370
239
  };
371
240
  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
241
  const SelectSheetImpl = (props) => {
717
242
  return <>{props.children}</>;
718
243
  };
@@ -726,13 +251,14 @@ const Select = withStaticProperties((props) => {
726
251
  value: valueProp,
727
252
  defaultValue,
728
253
  onValueChange,
729
- size: sizeProp,
254
+ size: sizeProp = "$4",
730
255
  sheetBreakpoint = false,
731
256
  dir
732
257
  } = props;
733
258
  const isSheet = useSelectBreakpointActive(sheetBreakpoint);
734
259
  const SelectImpl = isSheet ? SelectSheetImpl : SelectInlineImpl;
735
260
  const forceUpdate = React.useReducer(() => ({}), {})[1];
261
+ const [selectedItem, setSelectedItem] = React.useState(null);
736
262
  const [open, setOpen] = useControllableState({
737
263
  prop: openProp,
738
264
  defaultProp: defaultOpen || false,
@@ -754,7 +280,7 @@ const Select = withStaticProperties((props) => {
754
280
  selectedIndexRef.current = selectedIndex;
755
281
  activeIndexRef.current = activeIndex;
756
282
  });
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) => {
283
+ 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
284
  listContentRef.current[index] = value2;
759
285
  }} 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
286
  }, {
@@ -783,8 +309,9 @@ export {
783
309
  SelectSeparator,
784
310
  SelectSheetContents,
785
311
  SelectTrigger,
786
- SelectViewport,
787
- SelectViewportFrame,
788
- createSelectScope
312
+ getVisualOffsetTop,
313
+ isFirefox,
314
+ useSelectBreakpointActive,
315
+ useShowSelectSheet
789
316
  };
790
317
  //# sourceMappingURL=Select.js.map