@hot-updater/console 0.36.7 → 1.0.0-rc.0

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 (266) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/AnalyticsCapabilityContext-BCke57-7.js +1 -0
  3. package/.output/public/assets/BundleActivityChart-CnsBe_1J.js +42 -0
  4. package/.output/public/assets/BundleIdDisplay-Dky75zLU.js +1 -0
  5. package/.output/public/assets/alert-C-1KvDW8.js +1 -0
  6. package/.output/public/assets/analytics-Bqz0c-BT.js +1 -0
  7. package/.output/public/assets/analytics-api-CJdrTLLO.js +1 -0
  8. package/.output/public/assets/api-B_Rh-uzC.js +1 -0
  9. package/.output/public/assets/api-keys-BurCFhzH.js +1 -0
  10. package/.output/public/assets/api-keys-api-BEDJdQg3.js +1 -0
  11. package/.output/public/assets/badge-Bf0fZ-Gx.js +1 -0
  12. package/.output/public/assets/chart-no-axes-combined-FaYMGmQS.js +1 -0
  13. package/.output/public/assets/createServerFn-gM2-LFBy.js +3 -0
  14. package/.output/public/assets/dialog-BS60BRr2.js +1 -0
  15. package/.output/public/assets/dist-DspNKfMj.js +1 -0
  16. package/.output/public/assets/download-O-yNBc9H.js +1 -0
  17. package/.output/public/assets/field-Buq148-A.js +1 -0
  18. package/.output/public/assets/index-kFhd2S78.js +10 -0
  19. package/.output/public/assets/installations-BrQ-od41.js +2 -0
  20. package/.output/public/assets/installations-CGlZ3ROz.js +1 -0
  21. package/.output/public/assets/lazyRouteComponent-rPzgA7S-.js +1 -0
  22. package/.output/public/assets/loader-circle-DCYF-wJl.js +1 -0
  23. package/.output/public/assets/preload-helper-TKOBYGYD.js +1 -0
  24. package/.output/public/assets/refresh-cw-n8XYbPPj.js +1 -0
  25. package/.output/public/assets/routes-CrdokJ80.js +1 -0
  26. package/.output/public/assets/routes-DcQnVajO.js +2 -0
  27. package/.output/public/assets/search-DLhbWw3W.js +1 -0
  28. package/.output/public/assets/shield-check-DE_hVuHu.js +1 -0
  29. package/.output/public/assets/signing-HRexfjsH.js +1 -0
  30. package/.output/public/assets/styles-eB4EtvFS.css +2 -0
  31. package/.output/public/assets/table-D8CLieHX.js +1 -0
  32. package/.output/public/assets/textarea-YJLTVAoq.js +1 -0
  33. package/.output/public/assets/useMutation-JsGVjQMY.js +1 -0
  34. package/.output/public/assets/useOpenInteractionType-4cRD5xO0.js +1 -0
  35. package/.output/server/__23tanstack-start-server-fn-resolver-DBP9TQ7K.mjs +146 -0
  36. package/.output/server/_libs/@base-ui/react+[...].mjs +16124 -0
  37. package/.output/server/_libs/@reduxjs/toolkit+[...].mjs +1554 -0
  38. package/.output/server/_libs/@tanstack/react-router+[...].mjs +41 -10
  39. package/.output/server/_libs/@tanstack/react-router-ssr-query+[...].mjs +132 -0
  40. package/.output/server/_libs/d3-array.mjs +231 -0
  41. package/.output/server/_libs/d3-color.mjs +330 -0
  42. package/.output/server/_libs/d3-format.mjs +252 -0
  43. package/.output/server/_libs/d3-interpolate.mjs +207 -0
  44. package/.output/server/_libs/d3-path.mjs +77 -0
  45. package/.output/server/_libs/d3-scale+[...].mjs +1907 -0
  46. package/.output/server/_libs/d3-shape.mjs +818 -0
  47. package/.output/server/_libs/decimal.js-light.mjs +884 -0
  48. package/.output/server/_libs/es-toolkit.mjs +1134 -0
  49. package/.output/server/_libs/eventemitter3.mjs +236 -0
  50. package/.output/server/_libs/immer.mjs +532 -0
  51. package/.output/server/_libs/lucide-react.mjs +141 -13
  52. package/.output/server/_libs/next-themes.mjs +2 -2
  53. package/.output/server/_libs/react-redux+[...].mjs +205 -0
  54. package/.output/server/_libs/recharts+[...].mjs +14117 -0
  55. package/.output/server/_libs/sonner.mjs +2 -2
  56. package/.output/server/_libs/tanstack__query-core.mjs +114 -1
  57. package/.output/server/_libs/tanstack__react-query.mjs +3 -4
  58. package/.output/server/_runtime.mjs +10 -1
  59. package/.output/server/_ssr/AnalyticsCapabilityContext-ui4DX8GO.mjs +15 -0
  60. package/.output/server/_ssr/BundleActivityChart-BiB9ZORH.mjs +288 -0
  61. package/.output/server/_ssr/BundleIdDisplay-Czk6iR6p.mjs +13 -0
  62. package/.output/server/_ssr/alert-Dim3MGY5.mjs +86 -0
  63. package/.output/server/_ssr/analytics-DtMTn8fn.mjs +858 -0
  64. package/.output/server/_ssr/analytics-api-Cg1M5v_H.mjs +71 -0
  65. package/.output/server/_ssr/analytics-input-fRRRn0uA.mjs +96 -0
  66. package/.output/server/_ssr/analytics-rpc-DY5uXvHT.mjs +155 -0
  67. package/.output/server/_ssr/api-BTSv1tZb.mjs +282 -0
  68. package/.output/server/_ssr/api-keys-BnM_o2nS.mjs +300 -0
  69. package/.output/server/_ssr/api-keys-api-CIywsSF5.mjs +60 -0
  70. package/.output/server/_ssr/api-keys-rpc-BSp1wkIV.mjs +136 -0
  71. package/.output/server/_ssr/api-rpc-cG5wd_tO.mjs +1468 -0
  72. package/.output/server/_ssr/auth-BF8mbAgF.mjs +21 -0
  73. package/.output/server/_ssr/auth-rpc-BrJ6obHJ.mjs +24 -0
  74. package/.output/server/_ssr/auth.server-DwKoZoQM.mjs +50 -0
  75. package/.output/server/_ssr/badge-DCxbEeof.mjs +26 -0
  76. package/.output/server/_ssr/bundle-signing-rpc-COoQhW8E.mjs +16 -0
  77. package/.output/server/_ssr/bundle-signing.server-D5u8KkMp.mjs +51 -0
  78. package/.output/server/_ssr/config-Dv8qLDZ0.mjs +13 -0
  79. package/.output/server/_ssr/config.server-DEiLhKmy.mjs +361 -0
  80. package/.output/server/_ssr/{createServerFn-DzU0k62V.mjs → createServerFn-B2hcXoPM.mjs} +1 -1
  81. package/.output/server/_ssr/createServerRpc-DB29C_5p.mjs +12 -0
  82. package/.output/server/_ssr/{sidebar-Cv_H0_Jv.mjs → createSsrRpc-9P0S0lJ3.mjs} +68 -50
  83. package/.output/server/_ssr/databaseRows-CwbNwYSl.mjs +166 -0
  84. package/.output/server/_ssr/deleteBundle-Cu_XOMt0.mjs +66 -0
  85. package/.output/server/_ssr/dialog-CQuRMNZ4.mjs +170 -0
  86. package/.output/server/_ssr/dist-BVSLTpoP.mjs +250 -0
  87. package/.output/server/_ssr/downloadBundle-CNnYxYO2.mjs +24 -0
  88. package/.output/server/_ssr/{empty-plugin-adapters-B4HCzgmM.mjs → empty-plugin-adapters-B5QvGpEl.mjs} +1 -1
  89. package/.output/server/_ssr/field-DRIXKjZG.mjs +74 -0
  90. package/.output/server/_ssr/{getBundleChildren-CVtSiH5t.mjs → getBundleChildren-BcRMFoDF.mjs} +10 -18
  91. package/.output/server/_ssr/installations-B-azgAvX.mjs +19 -0
  92. package/.output/server/_ssr/installations-Ctvzp2JH.mjs +535 -0
  93. package/.output/server/_ssr/router-C-KUBfOi.mjs +513 -0
  94. package/.output/server/_ssr/routes-BM4ht9jb.mjs +2286 -0
  95. package/.output/server/_ssr/routes-Z7TwC6nC.mjs +37 -0
  96. package/.output/server/_ssr/runtime.server-awTLiiXW.mjs +527 -0
  97. package/.output/server/_ssr/server-BjzmvXnO.mjs +7468 -0
  98. package/.output/server/_ssr/signing-k8GxyBDF.mjs +202 -0
  99. package/.output/server/_ssr/ssr.mjs +4 -5740
  100. package/.output/server/_ssr/start-DpViQGnt.mjs +4 -0
  101. package/.output/server/_ssr/table-v1yCvYo7.mjs +53 -0
  102. package/.output/server/_ssr/textarea-DYHnskhb.mjs +14 -0
  103. package/.output/server/_ssr/uuidv7-BbJ-9D_I.mjs +31 -0
  104. package/.output/server/_tanstack-start-manifest_v-CH4StzJu.mjs +108 -0
  105. package/.output/server/index.mjs +256 -53
  106. package/README.md +29 -8
  107. package/lib/index.d.mts +36 -0
  108. package/lib/index.mjs +4 -0
  109. package/lib/vite-internal.mjs +127 -0
  110. package/lib/vite.d.mts +10 -0
  111. package/lib/vite.mjs +5 -0
  112. package/package.json +51 -29
  113. package/public/apple-touch-icon.png +0 -0
  114. package/public/favicon-16x16.png +0 -0
  115. package/public/favicon-32x32.png +0 -0
  116. package/public/favicon.ico +0 -0
  117. package/public/logo.svg +1 -0
  118. package/public/manifest.json +30 -0
  119. package/public/robots.txt +3 -0
  120. package/src/components/AppSidebar.tsx +159 -0
  121. package/src/components/BundleIdDisplay.tsx +18 -0
  122. package/src/components/ChannelBadge.tsx +31 -0
  123. package/src/components/ConsoleAccessPage.tsx +122 -0
  124. package/src/components/EnabledStatusIcon.tsx +54 -0
  125. package/src/components/HashValueDisplay.tsx +85 -0
  126. package/src/components/HotUpdaterLogo.tsx +30 -0
  127. package/src/components/NotFoundPage.tsx +33 -0
  128. package/src/components/PlatformIcon.tsx +39 -0
  129. package/src/components/RolloutPercentageBadge.tsx +28 -0
  130. package/src/components/ThemeProvider.tsx +116 -0
  131. package/src/components/TimestampDisplay.tsx +41 -0
  132. package/src/components/features/analytics/ActivityChart.tsx +150 -0
  133. package/src/components/features/analytics/AnalyticsCapabilityContext.tsx +24 -0
  134. package/src/components/features/analytics/AnalyticsControls.tsx +115 -0
  135. package/src/components/features/analytics/AnalyticsErrorAlert.tsx +21 -0
  136. package/src/components/features/analytics/AnalyticsOverview.tsx +208 -0
  137. package/src/components/features/analytics/BundleDistribution.tsx +133 -0
  138. package/src/components/features/analytics/BundleSelector.tsx +114 -0
  139. package/src/components/features/analytics/InstallationHistoryCard.tsx +248 -0
  140. package/src/components/features/analytics/InstallationMatchesCard.tsx +132 -0
  141. package/src/components/features/analytics/InstallationPageHeader.tsx +138 -0
  142. package/src/components/features/analytics/InstallationPagination.tsx +48 -0
  143. package/src/components/features/analytics/InstallationSearch.tsx +230 -0
  144. package/src/components/features/analytics/UpdateOutcomes.tsx +147 -0
  145. package/src/components/features/api-keys/ApiKeysPage.tsx +377 -0
  146. package/src/components/features/bundles/BundleActivityChart.tsx +193 -0
  147. package/src/components/features/bundles/BundleAnalyticsSummary.tsx +123 -0
  148. package/src/components/features/bundles/BundleChildrenPanel.tsx +201 -0
  149. package/src/components/features/bundles/BundleMetadata.tsx +136 -0
  150. package/src/components/features/bundles/RolloutCohortsDialog.tsx +201 -0
  151. package/src/components/features/channels/ChannelManagementDialog.tsx +228 -0
  152. package/src/components/features/releases/ReleaseEditorSheet.tsx +879 -0
  153. package/src/components/features/releases/ReleaseStateBadge.tsx +20 -0
  154. package/src/components/features/signing/BundleSigningPage.tsx +247 -0
  155. package/src/components/ui/alert-dialog.tsx +185 -0
  156. package/src/components/ui/alert.tsx +76 -0
  157. package/src/components/ui/badge.tsx +49 -0
  158. package/src/components/ui/button.tsx +58 -0
  159. package/src/components/ui/card.tsx +89 -0
  160. package/src/components/ui/chart.tsx +371 -0
  161. package/src/components/ui/combobox.tsx +303 -0
  162. package/src/components/ui/dialog.tsx +156 -0
  163. package/src/components/ui/dropdown-menu.tsx +270 -0
  164. package/src/components/ui/field.tsx +235 -0
  165. package/src/components/ui/input-group.tsx +147 -0
  166. package/src/components/ui/input.tsx +19 -0
  167. package/src/components/ui/label.tsx +25 -0
  168. package/src/components/ui/progress.tsx +84 -0
  169. package/src/components/ui/select.tsx +205 -0
  170. package/src/components/ui/separator.tsx +23 -0
  171. package/src/components/ui/sheet.tsx +132 -0
  172. package/src/components/ui/sidebar.tsx +779 -0
  173. package/src/components/ui/skeleton.tsx +13 -0
  174. package/src/components/ui/slider.tsx +56 -0
  175. package/src/components/ui/sonner.tsx +45 -0
  176. package/src/components/ui/switch.tsx +25 -0
  177. package/src/components/ui/table.tsx +114 -0
  178. package/src/components/ui/textarea.tsx +18 -0
  179. package/src/components/ui/toggle-group.tsx +89 -0
  180. package/src/components/ui/toggle.tsx +43 -0
  181. package/src/components/ui/tooltip.tsx +66 -0
  182. package/src/hooks/use-mobile.ts +30 -0
  183. package/src/index.ts +48 -0
  184. package/src/lib/analytics-api.ts +145 -0
  185. package/src/lib/analytics-error.ts +19 -0
  186. package/src/lib/analytics-input.ts +187 -0
  187. package/src/lib/analytics-overview.ts +170 -0
  188. package/src/lib/analytics-rpc.ts +218 -0
  189. package/src/lib/api-keys-api.ts +69 -0
  190. package/src/lib/api-keys-rpc.ts +87 -0
  191. package/src/lib/api-rpc.ts +478 -0
  192. package/src/lib/api.ts +444 -0
  193. package/src/lib/auth-rpc.ts +16 -0
  194. package/src/lib/bundle-signing-api.ts +14 -0
  195. package/src/lib/bundle-signing-rpc.ts +16 -0
  196. package/src/lib/constants.ts +1 -0
  197. package/src/lib/git.ts +51 -0
  198. package/src/lib/server/auth.server.ts +43 -0
  199. package/src/lib/server/bundle-signing.server.ts +100 -0
  200. package/src/lib/server/config.server.ts +109 -0
  201. package/src/lib/server/console-runtime.server.ts +70 -0
  202. package/src/lib/server/deleteBundle.ts +145 -0
  203. package/src/lib/server/downloadBundle.ts +46 -0
  204. package/src/lib/server/getBundleChildren.ts +130 -0
  205. package/src/lib/server/listReleases.ts +61 -0
  206. package/src/lib/server/releaseActivity.ts +27 -0
  207. package/src/lib/server/releaseReachability.ts +95 -0
  208. package/src/lib/server/runtime.server.ts +172 -0
  209. package/src/lib/utils.ts +9 -0
  210. package/src/logo.svg +1 -0
  211. package/src/routeTree.gen.ts +199 -0
  212. package/src/router.tsx +21 -0
  213. package/src/routes/-installations-search.ts +19 -0
  214. package/src/routes/-releases-search.ts +74 -0
  215. package/src/routes/__root.tsx +174 -0
  216. package/src/routes/analytics.tsx +139 -0
  217. package/src/routes/api/auth/$.ts +19 -0
  218. package/src/routes/api/bundles/$bundleId/download.ts +17 -0
  219. package/src/routes/api-keys.tsx +37 -0
  220. package/src/routes/index.tsx +982 -0
  221. package/src/routes/installations.tsx +194 -0
  222. package/src/routes/signing.tsx +37 -0
  223. package/src/styles.css +152 -0
  224. package/src/virtual-modules.d.ts +21 -0
  225. package/src/vite-env.d.ts +1 -0
  226. package/src/vite-internal.ts +195 -0
  227. package/src/vite.ts +12 -0
  228. package/.output/public/assets/dist-DJX53faP.js +0 -3
  229. package/.output/public/assets/index-Iylis5kY.js +0 -10
  230. package/.output/public/assets/routes-HT21hs0C.js +0 -54
  231. package/.output/public/assets/styles-C0Re4quB.css +0 -2
  232. package/.output/server/__23tanstack-start-server-fn-resolver-CgwgZ0-i.mjs +0 -66
  233. package/.output/server/_libs/@floating-ui/core+[...].mjs +0 -698
  234. package/.output/server/_libs/@floating-ui/dom+[...].mjs +0 -644
  235. package/.output/server/_libs/@floating-ui/react-dom+[...].mjs +0 -839
  236. package/.output/server/_libs/@radix-ui/react-alert-dialog+[...].mjs +0 -2138
  237. package/.output/server/_libs/@radix-ui/react-popper+[...].mjs +0 -308
  238. package/.output/server/_libs/@radix-ui/react-select+[...].mjs +0 -1038
  239. package/.output/server/_libs/@tanstack/devtools-event-client+[...].mjs +0 -196
  240. package/.output/server/_libs/@tanstack/form-core+[...].mjs +0 -3228
  241. package/.output/server/_libs/@tanstack/react-form+[...].mjs +0 -430
  242. package/.output/server/_libs/@tanstack/react-table+[...].mjs +0 -2382
  243. package/.output/server/_libs/radix-ui__number.mjs +0 -6
  244. package/.output/server/_libs/radix-ui__primitive.mjs +0 -9
  245. package/.output/server/_libs/radix-ui__react-arrow.mjs +0 -23
  246. package/.output/server/_libs/radix-ui__react-collection.mjs +0 -78
  247. package/.output/server/_libs/radix-ui__react-direction.mjs +0 -13
  248. package/.output/server/_libs/radix-ui__react-label.mjs +0 -22
  249. package/.output/server/_libs/radix-ui__react-separator.mjs +0 -30
  250. package/.output/server/_libs/radix-ui__react-slider.mjs +0 -510
  251. package/.output/server/_libs/radix-ui__react-switch.mjs +0 -157
  252. package/.output/server/_libs/radix-ui__react-tooltip.mjs +0 -493
  253. package/.output/server/_ssr/api-rpc-BIbDUKSz.mjs +0 -292
  254. package/.output/server/_ssr/config.server-BSS366KT.mjs +0 -41
  255. package/.output/server/_ssr/deleteBundle-BgbZTtpW.mjs +0 -141
  256. package/.output/server/_ssr/dist-KboydRVk.mjs +0 -120
  257. package/.output/server/_ssr/router-C3hqEy3k.mjs +0 -307
  258. package/.output/server/_ssr/routes-B0lQvvlC.mjs +0 -3048
  259. package/.output/server/_ssr/start-02sLteYG.mjs +0 -4
  260. package/.output/server/_ssr/storageProfile-FVkjPoGb.mjs +0 -9
  261. package/.output/server/_tanstack-start-manifest_v-Bpx52WOU.mjs +0 -20
  262. package/.output/server/node_modules/tslib/modules/index.js +0 -70
  263. package/.output/server/node_modules/tslib/modules/package.json +0 -3
  264. package/.output/server/node_modules/tslib/package.json +0 -47
  265. package/.output/server/node_modules/tslib/tslib.js +0 -484
  266. package/.output/server/package.json +0 -9
@@ -1,1038 +0,0 @@
1
- import { r as __toESM } from "../../_runtime.mjs";
2
- import { l as require_react_dom, u as require_react } from "../@floating-ui/react-dom+[...].mjs";
3
- import { C as useCallbackRef, D as useLayoutEffect2, E as useControllableState, N as useComposedRefs, O as createContextScope, P as require_jsx_runtime, S as DismissableLayer, T as Presence, _ as hideOthers, b as Portal, j as createSlot, k as Primitive, v as ReactRemoveScroll, w as useId, x as FocusScope, y as useFocusGuards } from "./react-alert-dialog+[...].mjs";
4
- import { t as createCollection } from "../radix-ui__react-collection.mjs";
5
- import { t as composeEventHandlers } from "../radix-ui__primitive.mjs";
6
- import { t as useDirection } from "../radix-ui__react-direction.mjs";
7
- import { a as createPopperScope, i as Root2, n as Arrow, r as Content, t as Anchor } from "./react-popper+[...].mjs";
8
- import { t as clamp } from "../radix-ui__number.mjs";
9
- //#region ../../node_modules/.pnpm/@radix-ui+react-visually-hidden@1.2.5_@types+react-dom@19.2.3_@types+react@19.2.15__@ty_57907524451428ebc21a88670ca0b799/node_modules/@radix-ui/react-visually-hidden/dist/index.mjs
10
- var import_react_dom = /* @__PURE__ */ __toESM(require_react_dom(), 1);
11
- var import_react = /* @__PURE__ */ __toESM(require_react(), 1);
12
- var import_jsx_runtime = require_jsx_runtime();
13
- var VISUALLY_HIDDEN_STYLES = Object.freeze({
14
- position: "absolute",
15
- border: 0,
16
- width: 1,
17
- height: 1,
18
- padding: 0,
19
- margin: -1,
20
- overflow: "hidden",
21
- clip: "rect(0, 0, 0, 0)",
22
- whiteSpace: "nowrap",
23
- wordWrap: "normal"
24
- });
25
- var NAME = "VisuallyHidden";
26
- var VisuallyHidden = import_react.forwardRef((props, forwardedRef) => {
27
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Primitive.span, {
28
- ...props,
29
- ref: forwardedRef,
30
- style: {
31
- ...VISUALLY_HIDDEN_STYLES,
32
- ...props.style
33
- }
34
- });
35
- });
36
- VisuallyHidden.displayName = NAME;
37
- var Root = VisuallyHidden;
38
- //#endregion
39
- //#region ../../node_modules/.pnpm/@radix-ui+react-use-previous@1.1.2_@types+react@19.2.15_react@19.2.6/node_modules/@radix-ui/react-use-previous/dist/index.mjs
40
- function usePrevious(value) {
41
- const ref = import_react.useRef({
42
- value,
43
- previous: value
44
- });
45
- return import_react.useMemo(() => {
46
- if (ref.current.value !== value) {
47
- ref.current.previous = ref.current.value;
48
- ref.current.value = value;
49
- }
50
- return ref.current.previous;
51
- }, [value]);
52
- }
53
- //#endregion
54
- //#region ../../node_modules/.pnpm/@radix-ui+react-select@2.3.0_@types+react-dom@19.2.3_@types+react@19.2.15__@types+react_ac7eb800be9df7939f38bd342d4df42b/node_modules/@radix-ui/react-select/dist/index.mjs
55
- var OPEN_KEYS = [
56
- " ",
57
- "Enter",
58
- "ArrowUp",
59
- "ArrowDown"
60
- ];
61
- var SELECTION_KEYS = [" ", "Enter"];
62
- var SELECT_NAME = "Select";
63
- var [Collection, useCollection, createCollectionScope] = createCollection(SELECT_NAME);
64
- var [createSelectContext, createSelectScope] = createContextScope(SELECT_NAME, [createCollectionScope, createPopperScope]);
65
- var usePopperScope = createPopperScope();
66
- var [SelectProviderImpl, useSelectContext] = createSelectContext(SELECT_NAME);
67
- var [SelectNativeOptionsProvider, useSelectNativeOptionsContext] = createSelectContext(SELECT_NAME);
68
- var PROVIDER_NAME = "SelectProvider";
69
- function SelectProvider(props) {
70
- const { __scopeSelect, children, open: openProp, defaultOpen, onOpenChange, value: valueProp, defaultValue, onValueChange, dir, name, autoComplete, disabled, required, form, internal_do_not_use_render } = props;
71
- const popperScope = usePopperScope(__scopeSelect);
72
- const [trigger, setTrigger] = import_react.useState(null);
73
- const [valueNode, setValueNode] = import_react.useState(null);
74
- const [valueNodeHasChildren, setValueNodeHasChildren] = import_react.useState(false);
75
- const direction = useDirection(dir);
76
- const [open, setOpen] = useControllableState({
77
- prop: openProp,
78
- defaultProp: defaultOpen ?? false,
79
- onChange: onOpenChange,
80
- caller: SELECT_NAME
81
- });
82
- const [value, setValue] = useControllableState({
83
- prop: valueProp,
84
- defaultProp: defaultValue,
85
- onChange: onValueChange,
86
- caller: SELECT_NAME
87
- });
88
- const triggerPointerDownPosRef = import_react.useRef(null);
89
- const isFormControl = trigger ? !!form || !!trigger.closest("form") : true;
90
- const [nativeOptionsSet, setNativeOptionsSet] = import_react.useState(/* @__PURE__ */ new Set());
91
- const contentId = useId();
92
- const nativeSelectKey = Array.from(nativeOptionsSet).map((option) => option.props.value).join(";");
93
- const handleNativeOptionAdd = import_react.useCallback((option) => {
94
- setNativeOptionsSet((prev) => new Set(prev).add(option));
95
- }, []);
96
- const handleNativeOptionRemove = import_react.useCallback((option) => {
97
- setNativeOptionsSet((prev) => {
98
- const optionsSet = new Set(prev);
99
- optionsSet.delete(option);
100
- return optionsSet;
101
- });
102
- }, []);
103
- const context = {
104
- required,
105
- trigger,
106
- onTriggerChange: setTrigger,
107
- valueNode,
108
- onValueNodeChange: setValueNode,
109
- valueNodeHasChildren,
110
- onValueNodeHasChildrenChange: setValueNodeHasChildren,
111
- contentId,
112
- value,
113
- onValueChange: setValue,
114
- open,
115
- onOpenChange: setOpen,
116
- dir: direction,
117
- triggerPointerDownPosRef,
118
- disabled,
119
- name,
120
- autoComplete,
121
- form,
122
- nativeOptions: nativeOptionsSet,
123
- nativeSelectKey,
124
- isFormControl
125
- };
126
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Root2, {
127
- ...popperScope,
128
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectProviderImpl, {
129
- scope: __scopeSelect,
130
- ...context,
131
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Collection.Provider, {
132
- scope: __scopeSelect,
133
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectNativeOptionsProvider, {
134
- scope: __scopeSelect,
135
- onNativeOptionAdd: handleNativeOptionAdd,
136
- onNativeOptionRemove: handleNativeOptionRemove,
137
- children: isFunction(internal_do_not_use_render) ? internal_do_not_use_render(context) : children
138
- })
139
- })
140
- })
141
- });
142
- }
143
- SelectProvider.displayName = PROVIDER_NAME;
144
- var Select = (props) => {
145
- const { __scopeSelect, children, ...providerProps } = props;
146
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectProvider, {
147
- __scopeSelect,
148
- ...providerProps,
149
- internal_do_not_use_render: ({ isFormControl }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [children, isFormControl ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectBubbleInput, { __scopeSelect }) : null] })
150
- });
151
- };
152
- Select.displayName = SELECT_NAME;
153
- var TRIGGER_NAME = "SelectTrigger";
154
- var SelectTrigger = import_react.forwardRef((props, forwardedRef) => {
155
- const { __scopeSelect, disabled = false, ...triggerProps } = props;
156
- const popperScope = usePopperScope(__scopeSelect);
157
- const context = useSelectContext(TRIGGER_NAME, __scopeSelect);
158
- const isDisabled = context.disabled || disabled;
159
- const composedRefs = useComposedRefs(forwardedRef, context.onTriggerChange);
160
- const getItems = useCollection(__scopeSelect);
161
- const pointerTypeRef = import_react.useRef("touch");
162
- const [searchRef, handleTypeaheadSearch, resetTypeahead] = useTypeaheadSearch((search) => {
163
- const enabledItems = getItems().filter((item) => !item.disabled);
164
- const nextItem = findNextItem(enabledItems, search, enabledItems.find((item) => item.value === context.value));
165
- if (nextItem !== void 0) context.onValueChange(nextItem.value);
166
- });
167
- const handleOpen = (pointerEvent) => {
168
- if (!isDisabled) {
169
- context.onOpenChange(true);
170
- resetTypeahead();
171
- }
172
- if (pointerEvent) context.triggerPointerDownPosRef.current = {
173
- x: Math.round(pointerEvent.pageX),
174
- y: Math.round(pointerEvent.pageY)
175
- };
176
- };
177
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Anchor, {
178
- asChild: true,
179
- ...popperScope,
180
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Primitive.button, {
181
- type: "button",
182
- role: "combobox",
183
- "aria-controls": context.open ? context.contentId : void 0,
184
- "aria-expanded": context.open,
185
- "aria-required": context.required,
186
- "aria-autocomplete": "none",
187
- dir: context.dir,
188
- "data-state": context.open ? "open" : "closed",
189
- disabled: isDisabled,
190
- "data-disabled": isDisabled ? "" : void 0,
191
- "data-placeholder": shouldShowPlaceholder(context.value) ? "" : void 0,
192
- ...triggerProps,
193
- ref: composedRefs,
194
- onClick: composeEventHandlers(triggerProps.onClick, (event) => {
195
- event.currentTarget.focus();
196
- if (pointerTypeRef.current !== "mouse") handleOpen(event);
197
- }),
198
- onPointerDown: composeEventHandlers(triggerProps.onPointerDown, (event) => {
199
- pointerTypeRef.current = event.pointerType;
200
- const target = event.target;
201
- if (target.hasPointerCapture(event.pointerId)) target.releasePointerCapture(event.pointerId);
202
- if (event.button === 0 && event.ctrlKey === false && event.pointerType === "mouse") {
203
- handleOpen(event);
204
- event.preventDefault();
205
- }
206
- }),
207
- onKeyDown: composeEventHandlers(triggerProps.onKeyDown, (event) => {
208
- const isTypingAhead = searchRef.current !== "";
209
- if (!(event.ctrlKey || event.altKey || event.metaKey) && event.key.length === 1) handleTypeaheadSearch(event.key);
210
- if (isTypingAhead && event.key === " ") return;
211
- if (OPEN_KEYS.includes(event.key)) {
212
- handleOpen();
213
- event.preventDefault();
214
- }
215
- })
216
- })
217
- });
218
- });
219
- SelectTrigger.displayName = TRIGGER_NAME;
220
- var VALUE_NAME = "SelectValue";
221
- var SelectValue = import_react.forwardRef((props, forwardedRef) => {
222
- const { __scopeSelect, className, style, children, placeholder = "", ...valueProps } = props;
223
- const context = useSelectContext(VALUE_NAME, __scopeSelect);
224
- const { onValueNodeHasChildrenChange } = context;
225
- const hasChildren = children !== void 0;
226
- const composedRefs = useComposedRefs(forwardedRef, context.onValueNodeChange);
227
- useLayoutEffect2(() => {
228
- onValueNodeHasChildrenChange(hasChildren);
229
- }, [onValueNodeHasChildrenChange, hasChildren]);
230
- const showPlaceholder = shouldShowPlaceholder(context.value);
231
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Primitive.span, {
232
- ...valueProps,
233
- asChild: showPlaceholder ? false : valueProps.asChild,
234
- ref: composedRefs,
235
- style: { pointerEvents: "none" },
236
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react.Fragment, { children: showPlaceholder ? placeholder : children }, showPlaceholder ? "placeholder" : "value")
237
- });
238
- });
239
- SelectValue.displayName = VALUE_NAME;
240
- var ICON_NAME = "SelectIcon";
241
- var SelectIcon = import_react.forwardRef((props, forwardedRef) => {
242
- const { __scopeSelect, children, ...iconProps } = props;
243
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Primitive.span, {
244
- "aria-hidden": true,
245
- ...iconProps,
246
- ref: forwardedRef,
247
- children: children || "▼"
248
- });
249
- });
250
- SelectIcon.displayName = ICON_NAME;
251
- var PORTAL_NAME = "SelectPortal";
252
- var [PortalProvider, usePortalContext] = createSelectContext(PORTAL_NAME, { forceMount: void 0 });
253
- var SelectPortal = (props) => {
254
- const { __scopeSelect, forceMount, ...portalProps } = props;
255
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PortalProvider, {
256
- scope: props.__scopeSelect,
257
- forceMount,
258
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Portal, {
259
- asChild: true,
260
- ...portalProps
261
- })
262
- });
263
- };
264
- SelectPortal.displayName = PORTAL_NAME;
265
- var CONTENT_NAME = "SelectContent";
266
- var SelectContent = import_react.forwardRef((props, forwardedRef) => {
267
- const portalContext = usePortalContext(CONTENT_NAME, props.__scopeSelect);
268
- const { forceMount = portalContext.forceMount, ...contentProps } = props;
269
- const context = useSelectContext(CONTENT_NAME, props.__scopeSelect);
270
- const [fragment, setFragment] = import_react.useState();
271
- useLayoutEffect2(() => {
272
- setFragment(new DocumentFragment());
273
- }, []);
274
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Presence, {
275
- present: forceMount || context.open,
276
- children: ({ present }) => present ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectContentImpl, {
277
- ...contentProps,
278
- ref: forwardedRef
279
- }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectContentFragment, {
280
- ...contentProps,
281
- fragment
282
- })
283
- });
284
- });
285
- SelectContent.displayName = CONTENT_NAME;
286
- var SelectContentFragment = import_react.forwardRef((props, forwardedRef) => {
287
- const { __scopeSelect, children, fragment } = props;
288
- if (!fragment) return null;
289
- return import_react_dom.createPortal(/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectContentProvider, {
290
- scope: __scopeSelect,
291
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Collection.Slot, {
292
- scope: __scopeSelect,
293
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
294
- ref: forwardedRef,
295
- children
296
- })
297
- })
298
- }), fragment);
299
- });
300
- SelectContentFragment.displayName = "SelectContentFragment";
301
- var CONTENT_MARGIN = 10;
302
- var [SelectContentProvider, useSelectContentContext] = createSelectContext(CONTENT_NAME);
303
- var CONTENT_IMPL_NAME = "SelectContentImpl";
304
- var Slot = createSlot("SelectContent.RemoveScroll");
305
- var SelectContentImpl = import_react.forwardRef((props, forwardedRef) => {
306
- const { __scopeSelect } = props;
307
- const { position = "item-aligned", onCloseAutoFocus, onEscapeKeyDown, onPointerDownOutside, side, sideOffset, align, alignOffset, arrowPadding, collisionBoundary, collisionPadding, sticky, hideWhenDetached, avoidCollisions, ...contentProps } = props;
308
- const context = useSelectContext(CONTENT_NAME, __scopeSelect);
309
- const [content, setContent] = import_react.useState(null);
310
- const [viewport, setViewport] = import_react.useState(null);
311
- const composedRefs = useComposedRefs(forwardedRef, (node) => setContent(node));
312
- const [selectedItem, setSelectedItem] = import_react.useState(null);
313
- const [selectedItemText, setSelectedItemText] = import_react.useState(null);
314
- const getItems = useCollection(__scopeSelect);
315
- const [isPositioned, setIsPositioned] = import_react.useState(false);
316
- const firstValidItemFoundRef = import_react.useRef(false);
317
- import_react.useEffect(() => {
318
- if (content) return hideOthers(content);
319
- }, [content]);
320
- useFocusGuards();
321
- const focusFirst = import_react.useCallback((candidates) => {
322
- const [firstItem, ...restItems] = getItems().map((item) => item.ref.current);
323
- const [lastItem] = restItems.slice(-1);
324
- const PREVIOUSLY_FOCUSED_ELEMENT = document.activeElement;
325
- for (const candidate of candidates) {
326
- if (candidate === PREVIOUSLY_FOCUSED_ELEMENT) return;
327
- candidate?.scrollIntoView({ block: "nearest" });
328
- if (candidate === firstItem && viewport) viewport.scrollTop = 0;
329
- if (candidate === lastItem && viewport) viewport.scrollTop = viewport.scrollHeight;
330
- candidate?.focus();
331
- if (document.activeElement !== PREVIOUSLY_FOCUSED_ELEMENT) return;
332
- }
333
- }, [getItems, viewport]);
334
- const focusSelectedItem = import_react.useCallback(() => focusFirst([selectedItem, content]), [
335
- focusFirst,
336
- selectedItem,
337
- content
338
- ]);
339
- import_react.useEffect(() => {
340
- if (isPositioned) focusSelectedItem();
341
- }, [isPositioned, focusSelectedItem]);
342
- const { onOpenChange, triggerPointerDownPosRef } = context;
343
- import_react.useEffect(() => {
344
- if (content) {
345
- let pointerMoveDelta = {
346
- x: 0,
347
- y: 0
348
- };
349
- const handlePointerMove = (event) => {
350
- pointerMoveDelta = {
351
- x: Math.abs(Math.round(event.pageX) - (triggerPointerDownPosRef.current?.x ?? 0)),
352
- y: Math.abs(Math.round(event.pageY) - (triggerPointerDownPosRef.current?.y ?? 0))
353
- };
354
- };
355
- const handlePointerUp = (event) => {
356
- if (pointerMoveDelta.x <= 10 && pointerMoveDelta.y <= 10) event.preventDefault();
357
- else if (!event.composedPath().includes(content)) onOpenChange(false);
358
- document.removeEventListener("pointermove", handlePointerMove);
359
- triggerPointerDownPosRef.current = null;
360
- };
361
- if (triggerPointerDownPosRef.current !== null) {
362
- document.addEventListener("pointermove", handlePointerMove);
363
- document.addEventListener("pointerup", handlePointerUp, {
364
- capture: true,
365
- once: true
366
- });
367
- }
368
- return () => {
369
- document.removeEventListener("pointermove", handlePointerMove);
370
- document.removeEventListener("pointerup", handlePointerUp, { capture: true });
371
- };
372
- }
373
- }, [
374
- content,
375
- onOpenChange,
376
- triggerPointerDownPosRef
377
- ]);
378
- import_react.useEffect(() => {
379
- const close = () => onOpenChange(false);
380
- window.addEventListener("blur", close);
381
- window.addEventListener("resize", close);
382
- return () => {
383
- window.removeEventListener("blur", close);
384
- window.removeEventListener("resize", close);
385
- };
386
- }, [onOpenChange]);
387
- const [searchRef, handleTypeaheadSearch] = useTypeaheadSearch((search) => {
388
- const enabledItems = getItems().filter((item) => !item.disabled);
389
- const nextItem = findNextItem(enabledItems, search, enabledItems.find((item) => item.ref.current === document.activeElement));
390
- if (nextItem) setTimeout(() => nextItem.ref.current.focus());
391
- });
392
- const itemRefCallback = import_react.useCallback((node, value, disabled) => {
393
- const isFirstValidItem = !firstValidItemFoundRef.current && !disabled;
394
- if (context.value !== void 0 && context.value === value || isFirstValidItem) {
395
- setSelectedItem(node);
396
- if (isFirstValidItem) firstValidItemFoundRef.current = true;
397
- }
398
- }, [context.value]);
399
- const handleItemLeave = import_react.useCallback(() => content?.focus(), [content]);
400
- const itemTextRefCallback = import_react.useCallback((node, value, disabled) => {
401
- const isFirstValidItem = !firstValidItemFoundRef.current && !disabled;
402
- if (context.value !== void 0 && context.value === value || isFirstValidItem) setSelectedItemText(node);
403
- }, [context.value]);
404
- const SelectPosition = position === "popper" ? SelectPopperPosition : SelectItemAlignedPosition;
405
- const popperContentProps = SelectPosition === SelectPopperPosition ? {
406
- side,
407
- sideOffset,
408
- align,
409
- alignOffset,
410
- arrowPadding,
411
- collisionBoundary,
412
- collisionPadding,
413
- sticky,
414
- hideWhenDetached,
415
- avoidCollisions
416
- } : {};
417
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectContentProvider, {
418
- scope: __scopeSelect,
419
- content,
420
- viewport,
421
- onViewportChange: setViewport,
422
- itemRefCallback,
423
- selectedItem,
424
- onItemLeave: handleItemLeave,
425
- itemTextRefCallback,
426
- focusSelectedItem,
427
- selectedItemText,
428
- position,
429
- isPositioned,
430
- searchRef,
431
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ReactRemoveScroll, {
432
- as: Slot,
433
- allowPinchZoom: true,
434
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FocusScope, {
435
- asChild: true,
436
- trapped: context.open,
437
- onMountAutoFocus: (event) => {
438
- event.preventDefault();
439
- },
440
- onUnmountAutoFocus: composeEventHandlers(onCloseAutoFocus, (event) => {
441
- context.trigger?.focus({ preventScroll: true });
442
- event.preventDefault();
443
- }),
444
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DismissableLayer, {
445
- asChild: true,
446
- disableOutsidePointerEvents: true,
447
- onEscapeKeyDown,
448
- onPointerDownOutside,
449
- onFocusOutside: (event) => event.preventDefault(),
450
- onDismiss: () => context.onOpenChange(false),
451
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectPosition, {
452
- role: "listbox",
453
- id: context.contentId,
454
- "data-state": context.open ? "open" : "closed",
455
- dir: context.dir,
456
- onContextMenu: (event) => event.preventDefault(),
457
- ...contentProps,
458
- ...popperContentProps,
459
- onPlaced: () => setIsPositioned(true),
460
- ref: composedRefs,
461
- style: {
462
- display: "flex",
463
- flexDirection: "column",
464
- outline: "none",
465
- ...contentProps.style
466
- },
467
- onKeyDown: composeEventHandlers(contentProps.onKeyDown, (event) => {
468
- const isModifierKey = event.ctrlKey || event.altKey || event.metaKey;
469
- if (event.key === "Tab") event.preventDefault();
470
- if (!isModifierKey && event.key.length === 1) handleTypeaheadSearch(event.key);
471
- if ([
472
- "ArrowUp",
473
- "ArrowDown",
474
- "Home",
475
- "End"
476
- ].includes(event.key)) {
477
- let candidateNodes = getItems().filter((item) => !item.disabled).map((item) => item.ref.current);
478
- if (["ArrowUp", "End"].includes(event.key)) candidateNodes = candidateNodes.slice().reverse();
479
- if (["ArrowUp", "ArrowDown"].includes(event.key)) {
480
- const currentElement = event.target;
481
- const currentIndex = candidateNodes.indexOf(currentElement);
482
- candidateNodes = candidateNodes.slice(currentIndex + 1);
483
- }
484
- setTimeout(() => focusFirst(candidateNodes));
485
- event.preventDefault();
486
- }
487
- })
488
- })
489
- })
490
- })
491
- })
492
- });
493
- });
494
- SelectContentImpl.displayName = CONTENT_IMPL_NAME;
495
- var ITEM_ALIGNED_POSITION_NAME = "SelectItemAlignedPosition";
496
- var SelectItemAlignedPosition = import_react.forwardRef((props, forwardedRef) => {
497
- const { __scopeSelect, onPlaced, ...popperProps } = props;
498
- const context = useSelectContext(CONTENT_NAME, __scopeSelect);
499
- const contentContext = useSelectContentContext(CONTENT_NAME, __scopeSelect);
500
- const [contentWrapper, setContentWrapper] = import_react.useState(null);
501
- const [content, setContent] = import_react.useState(null);
502
- const composedRefs = useComposedRefs(forwardedRef, (node) => setContent(node));
503
- const getItems = useCollection(__scopeSelect);
504
- const shouldExpandOnScrollRef = import_react.useRef(false);
505
- const shouldRepositionRef = import_react.useRef(true);
506
- const { viewport, selectedItem, selectedItemText, focusSelectedItem } = contentContext;
507
- const position = import_react.useCallback(() => {
508
- if (context.trigger && context.valueNode && contentWrapper && content && viewport && selectedItem && selectedItemText) {
509
- const triggerRect = context.trigger.getBoundingClientRect();
510
- const contentRect = content.getBoundingClientRect();
511
- const valueNodeRect = context.valueNode.getBoundingClientRect();
512
- const itemTextRect = selectedItemText.getBoundingClientRect();
513
- if (context.dir !== "rtl") {
514
- const itemTextOffset = itemTextRect.left - contentRect.left;
515
- const left = valueNodeRect.left - itemTextOffset;
516
- const leftDelta = triggerRect.left - left;
517
- const minContentWidth = triggerRect.width + leftDelta;
518
- const contentWidth = Math.max(minContentWidth, contentRect.width);
519
- const rightEdge = window.innerWidth - CONTENT_MARGIN;
520
- const clampedLeft = clamp(left, [CONTENT_MARGIN, Math.max(CONTENT_MARGIN, rightEdge - contentWidth)]);
521
- contentWrapper.style.minWidth = minContentWidth + "px";
522
- contentWrapper.style.left = clampedLeft + "px";
523
- } else {
524
- const itemTextOffset = contentRect.right - itemTextRect.right;
525
- const right = window.innerWidth - valueNodeRect.right - itemTextOffset;
526
- const rightDelta = window.innerWidth - triggerRect.right - right;
527
- const minContentWidth = triggerRect.width + rightDelta;
528
- const contentWidth = Math.max(minContentWidth, contentRect.width);
529
- const leftEdge = window.innerWidth - CONTENT_MARGIN;
530
- const clampedRight = clamp(right, [CONTENT_MARGIN, Math.max(CONTENT_MARGIN, leftEdge - contentWidth)]);
531
- contentWrapper.style.minWidth = minContentWidth + "px";
532
- contentWrapper.style.right = clampedRight + "px";
533
- }
534
- const items = getItems();
535
- const availableHeight = window.innerHeight - CONTENT_MARGIN * 2;
536
- const itemsHeight = viewport.scrollHeight;
537
- const contentStyles = window.getComputedStyle(content);
538
- const contentBorderTopWidth = parseInt(contentStyles.borderTopWidth, 10);
539
- const contentPaddingTop = parseInt(contentStyles.paddingTop, 10);
540
- const contentBorderBottomWidth = parseInt(contentStyles.borderBottomWidth, 10);
541
- const contentPaddingBottom = parseInt(contentStyles.paddingBottom, 10);
542
- const fullContentHeight = contentBorderTopWidth + contentPaddingTop + itemsHeight + contentPaddingBottom + contentBorderBottomWidth;
543
- const minContentHeight = Math.min(selectedItem.offsetHeight * 5, fullContentHeight);
544
- const viewportStyles = window.getComputedStyle(viewport);
545
- const viewportPaddingTop = parseInt(viewportStyles.paddingTop, 10);
546
- const viewportPaddingBottom = parseInt(viewportStyles.paddingBottom, 10);
547
- const topEdgeToTriggerMiddle = triggerRect.top + triggerRect.height / 2 - CONTENT_MARGIN;
548
- const triggerMiddleToBottomEdge = availableHeight - topEdgeToTriggerMiddle;
549
- const selectedItemHalfHeight = selectedItem.offsetHeight / 2;
550
- const itemOffsetMiddle = selectedItem.offsetTop + selectedItemHalfHeight;
551
- const contentTopToItemMiddle = contentBorderTopWidth + contentPaddingTop + itemOffsetMiddle;
552
- const itemMiddleToContentBottom = fullContentHeight - contentTopToItemMiddle;
553
- if (contentTopToItemMiddle <= topEdgeToTriggerMiddle) {
554
- const isLastItem = items.length > 0 && selectedItem === items[items.length - 1].ref.current;
555
- contentWrapper.style.bottom = "0px";
556
- const viewportOffsetBottom = content.clientHeight - viewport.offsetTop - viewport.offsetHeight;
557
- const height = contentTopToItemMiddle + Math.max(triggerMiddleToBottomEdge, selectedItemHalfHeight + (isLastItem ? viewportPaddingBottom : 0) + viewportOffsetBottom + contentBorderBottomWidth);
558
- contentWrapper.style.height = height + "px";
559
- } else {
560
- const isFirstItem = items.length > 0 && selectedItem === items[0].ref.current;
561
- contentWrapper.style.top = "0px";
562
- const height = Math.max(topEdgeToTriggerMiddle, contentBorderTopWidth + viewport.offsetTop + (isFirstItem ? viewportPaddingTop : 0) + selectedItemHalfHeight) + itemMiddleToContentBottom;
563
- contentWrapper.style.height = height + "px";
564
- viewport.scrollTop = contentTopToItemMiddle - topEdgeToTriggerMiddle + viewport.offsetTop;
565
- }
566
- contentWrapper.style.margin = `${CONTENT_MARGIN}px 0`;
567
- contentWrapper.style.minHeight = minContentHeight + "px";
568
- contentWrapper.style.maxHeight = availableHeight + "px";
569
- onPlaced?.();
570
- requestAnimationFrame(() => shouldExpandOnScrollRef.current = true);
571
- }
572
- }, [
573
- getItems,
574
- context.trigger,
575
- context.valueNode,
576
- contentWrapper,
577
- content,
578
- viewport,
579
- selectedItem,
580
- selectedItemText,
581
- context.dir,
582
- onPlaced
583
- ]);
584
- useLayoutEffect2(() => position(), [position]);
585
- const [contentZIndex, setContentZIndex] = import_react.useState();
586
- useLayoutEffect2(() => {
587
- if (content) setContentZIndex(window.getComputedStyle(content).zIndex);
588
- }, [content]);
589
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectViewportProvider, {
590
- scope: __scopeSelect,
591
- contentWrapper,
592
- shouldExpandOnScrollRef,
593
- onScrollButtonChange: import_react.useCallback((node) => {
594
- if (node && shouldRepositionRef.current === true) {
595
- position();
596
- focusSelectedItem?.();
597
- shouldRepositionRef.current = false;
598
- }
599
- }, [position, focusSelectedItem]),
600
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
601
- ref: setContentWrapper,
602
- style: {
603
- display: "flex",
604
- flexDirection: "column",
605
- position: "fixed",
606
- zIndex: contentZIndex
607
- },
608
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Primitive.div, {
609
- ...popperProps,
610
- ref: composedRefs,
611
- style: {
612
- boxSizing: "border-box",
613
- maxHeight: "100%",
614
- ...popperProps.style
615
- }
616
- })
617
- })
618
- });
619
- });
620
- SelectItemAlignedPosition.displayName = ITEM_ALIGNED_POSITION_NAME;
621
- var POPPER_POSITION_NAME = "SelectPopperPosition";
622
- var SelectPopperPosition = import_react.forwardRef((props, forwardedRef) => {
623
- const { __scopeSelect, align = "start", collisionPadding = CONTENT_MARGIN, ...popperProps } = props;
624
- const popperScope = usePopperScope(__scopeSelect);
625
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Content, {
626
- ...popperScope,
627
- ...popperProps,
628
- ref: forwardedRef,
629
- align,
630
- collisionPadding,
631
- style: {
632
- boxSizing: "border-box",
633
- ...popperProps.style,
634
- "--radix-select-content-transform-origin": "var(--radix-popper-transform-origin)",
635
- "--radix-select-content-available-width": "var(--radix-popper-available-width)",
636
- "--radix-select-content-available-height": "var(--radix-popper-available-height)",
637
- "--radix-select-trigger-width": "var(--radix-popper-anchor-width)",
638
- "--radix-select-trigger-height": "var(--radix-popper-anchor-height)"
639
- }
640
- });
641
- });
642
- SelectPopperPosition.displayName = POPPER_POSITION_NAME;
643
- var [SelectViewportProvider, useSelectViewportContext] = createSelectContext(CONTENT_NAME, {});
644
- var VIEWPORT_NAME = "SelectViewport";
645
- var SelectViewport = import_react.forwardRef((props, forwardedRef) => {
646
- const { __scopeSelect, nonce, ...viewportProps } = props;
647
- const contentContext = useSelectContentContext(VIEWPORT_NAME, __scopeSelect);
648
- const viewportContext = useSelectViewportContext(VIEWPORT_NAME, __scopeSelect);
649
- const composedRefs = useComposedRefs(forwardedRef, contentContext.onViewportChange);
650
- const prevScrollTopRef = import_react.useRef(0);
651
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", {
652
- dangerouslySetInnerHTML: { __html: `[data-radix-select-viewport]{scrollbar-width:none;-ms-overflow-style:none;-webkit-overflow-scrolling:touch;}[data-radix-select-viewport]::-webkit-scrollbar{display:none}` },
653
- nonce
654
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Collection.Slot, {
655
- scope: __scopeSelect,
656
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Primitive.div, {
657
- "data-radix-select-viewport": "",
658
- role: "presentation",
659
- ...viewportProps,
660
- ref: composedRefs,
661
- style: {
662
- position: "relative",
663
- flex: 1,
664
- overflow: "hidden auto",
665
- ...viewportProps.style
666
- },
667
- onScroll: composeEventHandlers(viewportProps.onScroll, (event) => {
668
- const viewport = event.currentTarget;
669
- const { contentWrapper, shouldExpandOnScrollRef } = viewportContext;
670
- if (shouldExpandOnScrollRef?.current && contentWrapper) {
671
- const scrolledBy = Math.abs(prevScrollTopRef.current - viewport.scrollTop);
672
- if (scrolledBy > 0) {
673
- const availableHeight = window.innerHeight - CONTENT_MARGIN * 2;
674
- const cssMinHeight = parseFloat(contentWrapper.style.minHeight);
675
- const cssHeight = parseFloat(contentWrapper.style.height);
676
- const prevHeight = Math.max(cssMinHeight, cssHeight);
677
- if (prevHeight < availableHeight) {
678
- const nextHeight = prevHeight + scrolledBy;
679
- const clampedNextHeight = Math.min(availableHeight, nextHeight);
680
- const heightDiff = nextHeight - clampedNextHeight;
681
- contentWrapper.style.height = clampedNextHeight + "px";
682
- if (contentWrapper.style.bottom === "0px") {
683
- viewport.scrollTop = heightDiff > 0 ? heightDiff : 0;
684
- contentWrapper.style.justifyContent = "flex-end";
685
- }
686
- }
687
- }
688
- }
689
- prevScrollTopRef.current = viewport.scrollTop;
690
- })
691
- })
692
- })] });
693
- });
694
- SelectViewport.displayName = VIEWPORT_NAME;
695
- var GROUP_NAME = "SelectGroup";
696
- var [SelectGroupContextProvider, useSelectGroupContext] = createSelectContext(GROUP_NAME);
697
- var SelectGroup = import_react.forwardRef((props, forwardedRef) => {
698
- const { __scopeSelect, ...groupProps } = props;
699
- const groupId = useId();
700
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectGroupContextProvider, {
701
- scope: __scopeSelect,
702
- id: groupId,
703
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Primitive.div, {
704
- role: "group",
705
- "aria-labelledby": groupId,
706
- ...groupProps,
707
- ref: forwardedRef
708
- })
709
- });
710
- });
711
- SelectGroup.displayName = GROUP_NAME;
712
- var LABEL_NAME = "SelectLabel";
713
- var SelectLabel = import_react.forwardRef((props, forwardedRef) => {
714
- const { __scopeSelect, ...labelProps } = props;
715
- const groupContext = useSelectGroupContext(LABEL_NAME, __scopeSelect);
716
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Primitive.div, {
717
- id: groupContext.id,
718
- ...labelProps,
719
- ref: forwardedRef
720
- });
721
- });
722
- SelectLabel.displayName = LABEL_NAME;
723
- var ITEM_NAME = "SelectItem";
724
- var [SelectItemContextProvider, useSelectItemContext] = createSelectContext(ITEM_NAME);
725
- var SelectItem = import_react.forwardRef((props, forwardedRef) => {
726
- const { __scopeSelect, value, disabled = false, textValue: textValueProp, ...itemProps } = props;
727
- const context = useSelectContext(ITEM_NAME, __scopeSelect);
728
- const contentContext = useSelectContentContext(ITEM_NAME, __scopeSelect);
729
- const isSelected = context.value === value;
730
- const [textValue, setTextValue] = import_react.useState(textValueProp ?? "");
731
- const [isFocused, setIsFocused] = import_react.useState(false);
732
- const composedRefs = useComposedRefs(forwardedRef, (node) => contentContext.itemRefCallback?.(node, value, disabled));
733
- const textId = useId();
734
- const pointerTypeRef = import_react.useRef("touch");
735
- const handleSelect = () => {
736
- if (!disabled) {
737
- context.onValueChange(value);
738
- context.onOpenChange(false);
739
- }
740
- };
741
- if (value === "") throw new Error("A <Select.Item /> must have a value prop that is not an empty string. This is because the Select value can be set to an empty string to clear the selection and show the placeholder.");
742
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectItemContextProvider, {
743
- scope: __scopeSelect,
744
- value,
745
- disabled,
746
- textId,
747
- isSelected,
748
- onItemTextChange: import_react.useCallback((node) => {
749
- setTextValue((prevTextValue) => prevTextValue || (node?.textContent ?? "").trim());
750
- }, []),
751
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Collection.ItemSlot, {
752
- scope: __scopeSelect,
753
- value,
754
- disabled,
755
- textValue,
756
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Primitive.div, {
757
- role: "option",
758
- "aria-labelledby": textId,
759
- "data-highlighted": isFocused ? "" : void 0,
760
- "aria-selected": isSelected && isFocused,
761
- "data-state": isSelected ? "checked" : "unchecked",
762
- "aria-disabled": disabled || void 0,
763
- "data-disabled": disabled ? "" : void 0,
764
- tabIndex: disabled ? void 0 : -1,
765
- ...itemProps,
766
- ref: composedRefs,
767
- onFocus: composeEventHandlers(itemProps.onFocus, () => setIsFocused(true)),
768
- onBlur: composeEventHandlers(itemProps.onBlur, () => setIsFocused(false)),
769
- onClick: composeEventHandlers(itemProps.onClick, () => {
770
- if (pointerTypeRef.current !== "mouse") handleSelect();
771
- }),
772
- onPointerUp: composeEventHandlers(itemProps.onPointerUp, () => {
773
- if (pointerTypeRef.current === "mouse") handleSelect();
774
- }),
775
- onPointerDown: composeEventHandlers(itemProps.onPointerDown, (event) => {
776
- pointerTypeRef.current = event.pointerType;
777
- }),
778
- onPointerMove: composeEventHandlers(itemProps.onPointerMove, (event) => {
779
- pointerTypeRef.current = event.pointerType;
780
- if (disabled) contentContext.onItemLeave?.();
781
- else if (pointerTypeRef.current === "mouse") event.currentTarget.focus({ preventScroll: true });
782
- }),
783
- onPointerLeave: composeEventHandlers(itemProps.onPointerLeave, (event) => {
784
- if (event.currentTarget === document.activeElement) contentContext.onItemLeave?.();
785
- }),
786
- onKeyDown: composeEventHandlers(itemProps.onKeyDown, (event) => {
787
- if (contentContext.searchRef?.current !== "" && event.key === " ") return;
788
- if (SELECTION_KEYS.includes(event.key)) handleSelect();
789
- if (event.key === " ") event.preventDefault();
790
- })
791
- })
792
- })
793
- });
794
- });
795
- SelectItem.displayName = ITEM_NAME;
796
- var ITEM_TEXT_NAME = "SelectItemText";
797
- var SelectItemText = import_react.forwardRef((props, forwardedRef) => {
798
- const { __scopeSelect, className, style, ...itemTextProps } = props;
799
- const context = useSelectContext(ITEM_TEXT_NAME, __scopeSelect);
800
- const contentContext = useSelectContentContext(ITEM_TEXT_NAME, __scopeSelect);
801
- const itemContext = useSelectItemContext(ITEM_TEXT_NAME, __scopeSelect);
802
- const nativeOptionsContext = useSelectNativeOptionsContext(ITEM_TEXT_NAME, __scopeSelect);
803
- const [itemTextNode, setItemTextNode] = import_react.useState(null);
804
- const composedRefs = useComposedRefs(forwardedRef, (node) => setItemTextNode(node), itemContext.onItemTextChange, (node) => contentContext.itemTextRefCallback?.(node, itemContext.value, itemContext.disabled));
805
- const textContent = itemTextNode?.textContent;
806
- const nativeOption = import_react.useMemo(() => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", {
807
- value: itemContext.value,
808
- disabled: itemContext.disabled,
809
- children: textContent
810
- }, itemContext.value), [
811
- itemContext.disabled,
812
- itemContext.value,
813
- textContent
814
- ]);
815
- const { onNativeOptionAdd, onNativeOptionRemove } = nativeOptionsContext;
816
- useLayoutEffect2(() => {
817
- onNativeOptionAdd(nativeOption);
818
- return () => onNativeOptionRemove(nativeOption);
819
- }, [
820
- onNativeOptionAdd,
821
- onNativeOptionRemove,
822
- nativeOption
823
- ]);
824
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Primitive.span, {
825
- id: itemContext.textId,
826
- ...itemTextProps,
827
- ref: composedRefs
828
- }), itemContext.isSelected && context.valueNode && !context.valueNodeHasChildren ? import_react_dom.createPortal(itemTextProps.children, context.valueNode) : null] });
829
- });
830
- SelectItemText.displayName = ITEM_TEXT_NAME;
831
- var ITEM_INDICATOR_NAME = "SelectItemIndicator";
832
- var SelectItemIndicator = import_react.forwardRef((props, forwardedRef) => {
833
- const { __scopeSelect, ...itemIndicatorProps } = props;
834
- return useSelectItemContext(ITEM_INDICATOR_NAME, __scopeSelect).isSelected ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Primitive.span, {
835
- "aria-hidden": true,
836
- ...itemIndicatorProps,
837
- ref: forwardedRef
838
- }) : null;
839
- });
840
- SelectItemIndicator.displayName = ITEM_INDICATOR_NAME;
841
- var SCROLL_UP_BUTTON_NAME = "SelectScrollUpButton";
842
- var SelectScrollUpButton = import_react.forwardRef((props, forwardedRef) => {
843
- const contentContext = useSelectContentContext(SCROLL_UP_BUTTON_NAME, props.__scopeSelect);
844
- const viewportContext = useSelectViewportContext(SCROLL_UP_BUTTON_NAME, props.__scopeSelect);
845
- const [canScrollUp, setCanScrollUp] = import_react.useState(false);
846
- const composedRefs = useComposedRefs(forwardedRef, viewportContext.onScrollButtonChange);
847
- useLayoutEffect2(() => {
848
- if (contentContext.viewport && contentContext.isPositioned) {
849
- let handleScroll2 = function() {
850
- setCanScrollUp(viewport.scrollTop > 0);
851
- };
852
- const viewport = contentContext.viewport;
853
- handleScroll2();
854
- viewport.addEventListener("scroll", handleScroll2);
855
- return () => viewport.removeEventListener("scroll", handleScroll2);
856
- }
857
- }, [contentContext.viewport, contentContext.isPositioned]);
858
- return canScrollUp ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectScrollButtonImpl, {
859
- ...props,
860
- ref: composedRefs,
861
- onAutoScroll: () => {
862
- const { viewport, selectedItem } = contentContext;
863
- if (viewport && selectedItem) viewport.scrollTop = viewport.scrollTop - selectedItem.offsetHeight;
864
- }
865
- }) : null;
866
- });
867
- SelectScrollUpButton.displayName = SCROLL_UP_BUTTON_NAME;
868
- var SCROLL_DOWN_BUTTON_NAME = "SelectScrollDownButton";
869
- var SelectScrollDownButton = import_react.forwardRef((props, forwardedRef) => {
870
- const contentContext = useSelectContentContext(SCROLL_DOWN_BUTTON_NAME, props.__scopeSelect);
871
- const viewportContext = useSelectViewportContext(SCROLL_DOWN_BUTTON_NAME, props.__scopeSelect);
872
- const [canScrollDown, setCanScrollDown] = import_react.useState(false);
873
- const composedRefs = useComposedRefs(forwardedRef, viewportContext.onScrollButtonChange);
874
- useLayoutEffect2(() => {
875
- if (contentContext.viewport && contentContext.isPositioned) {
876
- let handleScroll2 = function() {
877
- const maxScroll = viewport.scrollHeight - viewport.clientHeight;
878
- setCanScrollDown(Math.ceil(viewport.scrollTop) < maxScroll);
879
- };
880
- const viewport = contentContext.viewport;
881
- handleScroll2();
882
- viewport.addEventListener("scroll", handleScroll2);
883
- return () => viewport.removeEventListener("scroll", handleScroll2);
884
- }
885
- }, [contentContext.viewport, contentContext.isPositioned]);
886
- return canScrollDown ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectScrollButtonImpl, {
887
- ...props,
888
- ref: composedRefs,
889
- onAutoScroll: () => {
890
- const { viewport, selectedItem } = contentContext;
891
- if (viewport && selectedItem) viewport.scrollTop = viewport.scrollTop + selectedItem.offsetHeight;
892
- }
893
- }) : null;
894
- });
895
- SelectScrollDownButton.displayName = SCROLL_DOWN_BUTTON_NAME;
896
- var SelectScrollButtonImpl = import_react.forwardRef((props, forwardedRef) => {
897
- const { __scopeSelect, onAutoScroll, ...scrollIndicatorProps } = props;
898
- const contentContext = useSelectContentContext("SelectScrollButton", __scopeSelect);
899
- const autoScrollTimerRef = import_react.useRef(null);
900
- const getItems = useCollection(__scopeSelect);
901
- const clearAutoScrollTimer = import_react.useCallback(() => {
902
- if (autoScrollTimerRef.current !== null) {
903
- window.clearInterval(autoScrollTimerRef.current);
904
- autoScrollTimerRef.current = null;
905
- }
906
- }, []);
907
- import_react.useEffect(() => {
908
- return () => clearAutoScrollTimer();
909
- }, [clearAutoScrollTimer]);
910
- useLayoutEffect2(() => {
911
- getItems().find((item) => item.ref.current === document.activeElement)?.ref.current?.scrollIntoView({ block: "nearest" });
912
- }, [getItems]);
913
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Primitive.div, {
914
- "aria-hidden": true,
915
- ...scrollIndicatorProps,
916
- ref: forwardedRef,
917
- style: {
918
- flexShrink: 0,
919
- ...scrollIndicatorProps.style
920
- },
921
- onPointerDown: composeEventHandlers(scrollIndicatorProps.onPointerDown, () => {
922
- if (autoScrollTimerRef.current === null) autoScrollTimerRef.current = window.setInterval(onAutoScroll, 50);
923
- }),
924
- onPointerMove: composeEventHandlers(scrollIndicatorProps.onPointerMove, () => {
925
- contentContext.onItemLeave?.();
926
- if (autoScrollTimerRef.current === null) autoScrollTimerRef.current = window.setInterval(onAutoScroll, 50);
927
- }),
928
- onPointerLeave: composeEventHandlers(scrollIndicatorProps.onPointerLeave, () => {
929
- clearAutoScrollTimer();
930
- })
931
- });
932
- });
933
- var SEPARATOR_NAME = "SelectSeparator";
934
- var SelectSeparator = import_react.forwardRef((props, forwardedRef) => {
935
- const { __scopeSelect, ...separatorProps } = props;
936
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Primitive.div, {
937
- "aria-hidden": true,
938
- ...separatorProps,
939
- ref: forwardedRef
940
- });
941
- });
942
- SelectSeparator.displayName = SEPARATOR_NAME;
943
- var ARROW_NAME = "SelectArrow";
944
- var SelectArrow = import_react.forwardRef((props, forwardedRef) => {
945
- const { __scopeSelect, ...arrowProps } = props;
946
- const popperScope = usePopperScope(__scopeSelect);
947
- return useSelectContentContext(ARROW_NAME, __scopeSelect).position === "popper" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Arrow, {
948
- ...popperScope,
949
- ...arrowProps,
950
- ref: forwardedRef
951
- }) : null;
952
- });
953
- SelectArrow.displayName = ARROW_NAME;
954
- var BUBBLE_INPUT_NAME = "SelectBubbleInput";
955
- var SelectBubbleInput = import_react.forwardRef(({ __scopeSelect, ...props }, forwardedRef) => {
956
- const context = useSelectContext(BUBBLE_INPUT_NAME, __scopeSelect);
957
- const { value, onValueChange, required, disabled, name, autoComplete, form } = context;
958
- const { nativeOptions, nativeSelectKey } = context;
959
- const ref = import_react.useRef(null);
960
- const composedRefs = useComposedRefs(forwardedRef, ref);
961
- const selectValue = value ?? "";
962
- const prevValue = usePrevious(selectValue);
963
- import_react.useEffect(() => {
964
- const select = ref.current;
965
- if (!select) return;
966
- const selectProto = window.HTMLSelectElement.prototype;
967
- const setValue = Object.getOwnPropertyDescriptor(selectProto, "value").set;
968
- if (prevValue !== selectValue && setValue) {
969
- const event = new Event("change", { bubbles: true });
970
- setValue.call(select, selectValue);
971
- select.dispatchEvent(event);
972
- }
973
- }, [prevValue, selectValue]);
974
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Primitive.select, {
975
- "aria-hidden": true,
976
- required,
977
- tabIndex: -1,
978
- name,
979
- autoComplete,
980
- disabled,
981
- form,
982
- onChange: (event) => onValueChange(event.target.value),
983
- ...props,
984
- style: {
985
- ...VISUALLY_HIDDEN_STYLES,
986
- ...props.style
987
- },
988
- ref: composedRefs,
989
- defaultValue: selectValue,
990
- children: [shouldShowPlaceholder(value) ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "" }) : null, Array.from(nativeOptions)]
991
- }, nativeSelectKey);
992
- });
993
- SelectBubbleInput.displayName = BUBBLE_INPUT_NAME;
994
- function isFunction(value) {
995
- return typeof value === "function";
996
- }
997
- function shouldShowPlaceholder(value) {
998
- return value === "" || value === void 0;
999
- }
1000
- function useTypeaheadSearch(onSearchChange) {
1001
- const handleSearchChange = useCallbackRef(onSearchChange);
1002
- const searchRef = import_react.useRef("");
1003
- const timerRef = import_react.useRef(0);
1004
- const handleTypeaheadSearch = import_react.useCallback((key) => {
1005
- const search = searchRef.current + key;
1006
- handleSearchChange(search);
1007
- (function updateSearch(value) {
1008
- searchRef.current = value;
1009
- window.clearTimeout(timerRef.current);
1010
- if (value !== "") timerRef.current = window.setTimeout(() => updateSearch(""), 1e3);
1011
- })(search);
1012
- }, [handleSearchChange]);
1013
- const resetTypeahead = import_react.useCallback(() => {
1014
- searchRef.current = "";
1015
- window.clearTimeout(timerRef.current);
1016
- }, []);
1017
- import_react.useEffect(() => {
1018
- return () => window.clearTimeout(timerRef.current);
1019
- }, []);
1020
- return [
1021
- searchRef,
1022
- handleTypeaheadSearch,
1023
- resetTypeahead
1024
- ];
1025
- }
1026
- function findNextItem(items, search, currentItem) {
1027
- const normalizedSearch = search.length > 1 && Array.from(search).every((char) => char === search[0]) ? search[0] : search;
1028
- const currentItemIndex = currentItem ? items.indexOf(currentItem) : -1;
1029
- let wrappedItems = wrapArray(items, Math.max(currentItemIndex, 0));
1030
- if (normalizedSearch.length === 1) wrappedItems = wrappedItems.filter((v) => v !== currentItem);
1031
- const nextItem = wrappedItems.find((item) => item.textValue.toLowerCase().startsWith(normalizedSearch.toLowerCase()));
1032
- return nextItem !== currentItem ? nextItem : void 0;
1033
- }
1034
- function wrapArray(array, startIndex) {
1035
- return array.map((_, index) => array[(startIndex + index) % array.length]);
1036
- }
1037
- //#endregion
1038
- export { SelectItemIndicator as a, SelectScrollDownButton as c, SelectValue as d, SelectViewport as f, SelectItem as i, SelectScrollUpButton as l, Root as m, SelectContent as n, SelectItemText as o, usePrevious as p, SelectIcon as r, SelectPortal as s, Select as t, SelectTrigger as u };