infinity-ui-elements 1.14.22 → 1.15.1

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.
package/dist/index.esm.js CHANGED
@@ -1,12 +1,14 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
2
  import * as React from 'react';
3
+ import { useLayoutEffect } from 'react';
3
4
  import { cva } from 'class-variance-authority';
4
- import { Slot } from '@radix-ui/react-slot';
5
+ import { Slot, createSlot } from '@radix-ui/react-slot';
5
6
  import { PulseLoader, ClipLoader } from 'react-spinners';
6
7
  import { clsx } from 'clsx';
7
8
  import { twMerge } from 'tailwind-merge';
8
9
  import { ExternalLink, Calendar, X, ChevronLeft, ChevronRight, Loader2, Search } from 'lucide-react';
9
- import { createPortal } from 'react-dom';
10
+ import * as ReactDOM from 'react-dom';
11
+ import ReactDOM__default, { createPortal } from 'react-dom';
10
12
  import Calendar$1 from 'react-calendar';
11
13
  import 'react-calendar/dist/Calendar.css';
12
14
  import { flexRender } from '@tanstack/react-table';
@@ -1943,233 +1945,3398 @@ const Counter = React.forwardRef(({ value, max, size = "medium", color = "neutra
1943
1945
  });
1944
1946
  Counter.displayName = "Counter";
1945
1947
 
1946
- const tooltipVariants = cva("fixed z-50 bg-popup-fill-intense text-action-ink-on-primary-normal rounded-medium border border-popup-outline-subtle flex flex-col p-4 rounded-xlarge min-w-[200px] max-w-[300px] transition-opacity duration-200", {
1947
- variants: {
1948
- isVisible: {
1949
- true: "opacity-100 pointer-events-auto shadow-[0_4px_20px_rgba(0,0,0,0.15)]",
1950
- false: "opacity-0 pointer-events-none",
1951
- },
1952
- },
1953
- defaultVariants: {
1954
- isVisible: false,
1948
+ // src/primitive.tsx
1949
+ function composeEventHandlers(originalEventHandler, ourEventHandler, { checkForDefaultPrevented = true } = {}) {
1950
+ return function handleEvent(event) {
1951
+ originalEventHandler?.(event);
1952
+ if (checkForDefaultPrevented === false || !event.defaultPrevented) {
1953
+ return ourEventHandler?.(event);
1954
+ }
1955
+ };
1956
+ }
1957
+
1958
+ // packages/react/context/src/create-context.tsx
1959
+ function createContextScope(scopeName, createContextScopeDeps = []) {
1960
+ let defaultContexts = [];
1961
+ function createContext3(rootComponentName, defaultContext) {
1962
+ const BaseContext = React.createContext(defaultContext);
1963
+ const index = defaultContexts.length;
1964
+ defaultContexts = [...defaultContexts, defaultContext];
1965
+ const Provider = (props) => {
1966
+ const { scope, children, ...context } = props;
1967
+ const Context = scope?.[scopeName]?.[index] || BaseContext;
1968
+ const value = React.useMemo(() => context, Object.values(context));
1969
+ return /* @__PURE__ */ jsx(Context.Provider, { value, children });
1970
+ };
1971
+ Provider.displayName = rootComponentName + "Provider";
1972
+ function useContext2(consumerName, scope) {
1973
+ const Context = scope?.[scopeName]?.[index] || BaseContext;
1974
+ const context = React.useContext(Context);
1975
+ if (context) return context;
1976
+ if (defaultContext !== void 0) return defaultContext;
1977
+ throw new Error(`\`${consumerName}\` must be used within \`${rootComponentName}\``);
1978
+ }
1979
+ return [Provider, useContext2];
1980
+ }
1981
+ const createScope = () => {
1982
+ const scopeContexts = defaultContexts.map((defaultContext) => {
1983
+ return React.createContext(defaultContext);
1984
+ });
1985
+ return function useScope(scope) {
1986
+ const contexts = scope?.[scopeName] || scopeContexts;
1987
+ return React.useMemo(
1988
+ () => ({ [`__scope${scopeName}`]: { ...scope, [scopeName]: contexts } }),
1989
+ [scope, contexts]
1990
+ );
1991
+ };
1992
+ };
1993
+ createScope.scopeName = scopeName;
1994
+ return [createContext3, composeContextScopes(createScope, ...createContextScopeDeps)];
1995
+ }
1996
+ function composeContextScopes(...scopes) {
1997
+ const baseScope = scopes[0];
1998
+ if (scopes.length === 1) return baseScope;
1999
+ const createScope = () => {
2000
+ const scopeHooks = scopes.map((createScope2) => ({
2001
+ useScope: createScope2(),
2002
+ scopeName: createScope2.scopeName
2003
+ }));
2004
+ return function useComposedScopes(overrideScopes) {
2005
+ const nextScopes = scopeHooks.reduce((nextScopes2, { useScope, scopeName }) => {
2006
+ const scopeProps = useScope(overrideScopes);
2007
+ const currentScope = scopeProps[`__scope${scopeName}`];
2008
+ return { ...nextScopes2, ...currentScope };
2009
+ }, {});
2010
+ return React.useMemo(() => ({ [`__scope${baseScope.scopeName}`]: nextScopes }), [nextScopes]);
2011
+ };
2012
+ };
2013
+ createScope.scopeName = baseScope.scopeName;
2014
+ return createScope;
2015
+ }
2016
+
2017
+ // packages/react/use-layout-effect/src/use-layout-effect.tsx
2018
+ var useLayoutEffect2 = globalThis?.document ? React.useLayoutEffect : () => {
2019
+ };
2020
+
2021
+ // src/use-controllable-state.tsx
2022
+ var useInsertionEffect = React[" useInsertionEffect ".trim().toString()] || useLayoutEffect2;
2023
+ function useControllableState({
2024
+ prop,
2025
+ defaultProp,
2026
+ onChange = () => {
2027
+ },
2028
+ caller
2029
+ }) {
2030
+ const [uncontrolledProp, setUncontrolledProp, onChangeRef] = useUncontrolledState({
2031
+ defaultProp,
2032
+ onChange
2033
+ });
2034
+ const isControlled = prop !== void 0;
2035
+ const value = isControlled ? prop : uncontrolledProp;
2036
+ {
2037
+ const isControlledRef = React.useRef(prop !== void 0);
2038
+ React.useEffect(() => {
2039
+ const wasControlled = isControlledRef.current;
2040
+ if (wasControlled !== isControlled) {
2041
+ const from = wasControlled ? "controlled" : "uncontrolled";
2042
+ const to = isControlled ? "controlled" : "uncontrolled";
2043
+ console.warn(
2044
+ `${caller} is changing from ${from} to ${to}. Components should not switch from controlled to uncontrolled (or vice versa). Decide between using a controlled or uncontrolled value for the lifetime of the component.`
2045
+ );
2046
+ }
2047
+ isControlledRef.current = isControlled;
2048
+ }, [isControlled, caller]);
2049
+ }
2050
+ const setValue = React.useCallback(
2051
+ (nextValue) => {
2052
+ if (isControlled) {
2053
+ const value2 = isFunction(nextValue) ? nextValue(prop) : nextValue;
2054
+ if (value2 !== prop) {
2055
+ onChangeRef.current?.(value2);
2056
+ }
2057
+ } else {
2058
+ setUncontrolledProp(nextValue);
2059
+ }
1955
2060
  },
2061
+ [isControlled, prop, setUncontrolledProp, onChangeRef]
2062
+ );
2063
+ return [value, setValue];
2064
+ }
2065
+ function useUncontrolledState({
2066
+ defaultProp,
2067
+ onChange
2068
+ }) {
2069
+ const [value, setValue] = React.useState(defaultProp);
2070
+ const prevValueRef = React.useRef(value);
2071
+ const onChangeRef = React.useRef(onChange);
2072
+ useInsertionEffect(() => {
2073
+ onChangeRef.current = onChange;
2074
+ }, [onChange]);
2075
+ React.useEffect(() => {
2076
+ if (prevValueRef.current !== value) {
2077
+ onChangeRef.current?.(value);
2078
+ prevValueRef.current = value;
2079
+ }
2080
+ }, [value, prevValueRef]);
2081
+ return [value, setValue, onChangeRef];
2082
+ }
2083
+ function isFunction(value) {
2084
+ return typeof value === "function";
2085
+ }
2086
+
2087
+ // packages/react/compose-refs/src/compose-refs.tsx
2088
+ function setRef(ref, value) {
2089
+ if (typeof ref === "function") {
2090
+ return ref(value);
2091
+ } else if (ref !== null && ref !== void 0) {
2092
+ ref.current = value;
2093
+ }
2094
+ }
2095
+ function composeRefs(...refs) {
2096
+ return (node) => {
2097
+ let hasCleanup = false;
2098
+ const cleanups = refs.map((ref) => {
2099
+ const cleanup = setRef(ref, node);
2100
+ if (!hasCleanup && typeof cleanup == "function") {
2101
+ hasCleanup = true;
2102
+ }
2103
+ return cleanup;
2104
+ });
2105
+ if (hasCleanup) {
2106
+ return () => {
2107
+ for (let i = 0; i < cleanups.length; i++) {
2108
+ const cleanup = cleanups[i];
2109
+ if (typeof cleanup == "function") {
2110
+ cleanup();
2111
+ } else {
2112
+ setRef(refs[i], null);
2113
+ }
2114
+ }
2115
+ };
2116
+ }
2117
+ };
2118
+ }
2119
+ function useComposedRefs(...refs) {
2120
+ return React.useCallback(composeRefs(...refs), refs);
2121
+ }
2122
+
2123
+ /**
2124
+ * Custom positioning reference element.
2125
+ * @see https://floating-ui.com/docs/virtual-elements
2126
+ */
2127
+
2128
+ const sides = ['top', 'right', 'bottom', 'left'];
2129
+ const min = Math.min;
2130
+ const max = Math.max;
2131
+ const round = Math.round;
2132
+ const floor = Math.floor;
2133
+ const createCoords = v => ({
2134
+ x: v,
2135
+ y: v
1956
2136
  });
1957
- const tooltipArrowVariants = cva("absolute w-0 h-0 border-solid border-[6px] -translate-x-1/2", {
1958
- variants: {
1959
- placement: {
1960
- "top-start": "top-full border-t-popup-fill-intense border-x-transparent border-b-transparent",
1961
- top: "top-full border-t-popup-fill-intense border-x-transparent border-b-transparent",
1962
- "top-end": "top-full border-t-popup-fill-intense border-x-transparent border-b-transparent",
1963
- "bottom-start": "bottom-full border-b-popup-fill-intense border-x-transparent border-t-transparent",
1964
- bottom: "bottom-full border-b-popup-fill-intense border-x-transparent border-t-transparent",
1965
- "bottom-end": "bottom-full border-b-popup-fill-intense border-x-transparent border-t-transparent",
1966
- },
1967
- },
1968
- defaultVariants: {
1969
- placement: "top",
1970
- },
2137
+ const oppositeSideMap = {
2138
+ left: 'right',
2139
+ right: 'left',
2140
+ bottom: 'top',
2141
+ top: 'bottom'
2142
+ };
2143
+ function clamp(start, value, end) {
2144
+ return max(start, min(value, end));
2145
+ }
2146
+ function evaluate(value, param) {
2147
+ return typeof value === 'function' ? value(param) : value;
2148
+ }
2149
+ function getSide(placement) {
2150
+ return placement.split('-')[0];
2151
+ }
2152
+ function getAlignment(placement) {
2153
+ return placement.split('-')[1];
2154
+ }
2155
+ function getOppositeAxis(axis) {
2156
+ return axis === 'x' ? 'y' : 'x';
2157
+ }
2158
+ function getAxisLength(axis) {
2159
+ return axis === 'y' ? 'height' : 'width';
2160
+ }
2161
+ function getSideAxis(placement) {
2162
+ const firstChar = placement[0];
2163
+ return firstChar === 't' || firstChar === 'b' ? 'y' : 'x';
2164
+ }
2165
+ function getAlignmentAxis(placement) {
2166
+ return getOppositeAxis(getSideAxis(placement));
2167
+ }
2168
+ function getAlignmentSides(placement, rects, rtl) {
2169
+ if (rtl === void 0) {
2170
+ rtl = false;
2171
+ }
2172
+ const alignment = getAlignment(placement);
2173
+ const alignmentAxis = getAlignmentAxis(placement);
2174
+ const length = getAxisLength(alignmentAxis);
2175
+ let mainAlignmentSide = alignmentAxis === 'x' ? alignment === (rtl ? 'end' : 'start') ? 'right' : 'left' : alignment === 'start' ? 'bottom' : 'top';
2176
+ if (rects.reference[length] > rects.floating[length]) {
2177
+ mainAlignmentSide = getOppositePlacement(mainAlignmentSide);
2178
+ }
2179
+ return [mainAlignmentSide, getOppositePlacement(mainAlignmentSide)];
2180
+ }
2181
+ function getExpandedPlacements(placement) {
2182
+ const oppositePlacement = getOppositePlacement(placement);
2183
+ return [getOppositeAlignmentPlacement(placement), oppositePlacement, getOppositeAlignmentPlacement(oppositePlacement)];
2184
+ }
2185
+ function getOppositeAlignmentPlacement(placement) {
2186
+ return placement.includes('start') ? placement.replace('start', 'end') : placement.replace('end', 'start');
2187
+ }
2188
+ const lrPlacement = ['left', 'right'];
2189
+ const rlPlacement = ['right', 'left'];
2190
+ const tbPlacement = ['top', 'bottom'];
2191
+ const btPlacement = ['bottom', 'top'];
2192
+ function getSideList(side, isStart, rtl) {
2193
+ switch (side) {
2194
+ case 'top':
2195
+ case 'bottom':
2196
+ if (rtl) return isStart ? rlPlacement : lrPlacement;
2197
+ return isStart ? lrPlacement : rlPlacement;
2198
+ case 'left':
2199
+ case 'right':
2200
+ return isStart ? tbPlacement : btPlacement;
2201
+ default:
2202
+ return [];
2203
+ }
2204
+ }
2205
+ function getOppositeAxisPlacements(placement, flipAlignment, direction, rtl) {
2206
+ const alignment = getAlignment(placement);
2207
+ let list = getSideList(getSide(placement), direction === 'start', rtl);
2208
+ if (alignment) {
2209
+ list = list.map(side => side + "-" + alignment);
2210
+ if (flipAlignment) {
2211
+ list = list.concat(list.map(getOppositeAlignmentPlacement));
2212
+ }
2213
+ }
2214
+ return list;
2215
+ }
2216
+ function getOppositePlacement(placement) {
2217
+ const side = getSide(placement);
2218
+ return oppositeSideMap[side] + placement.slice(side.length);
2219
+ }
2220
+ function expandPaddingObject(padding) {
2221
+ return {
2222
+ top: 0,
2223
+ right: 0,
2224
+ bottom: 0,
2225
+ left: 0,
2226
+ ...padding
2227
+ };
2228
+ }
2229
+ function getPaddingObject(padding) {
2230
+ return typeof padding !== 'number' ? expandPaddingObject(padding) : {
2231
+ top: padding,
2232
+ right: padding,
2233
+ bottom: padding,
2234
+ left: padding
2235
+ };
2236
+ }
2237
+ function rectToClientRect(rect) {
2238
+ const {
2239
+ x,
2240
+ y,
2241
+ width,
2242
+ height
2243
+ } = rect;
2244
+ return {
2245
+ width,
2246
+ height,
2247
+ top: y,
2248
+ left: x,
2249
+ right: x + width,
2250
+ bottom: y + height,
2251
+ x,
2252
+ y
2253
+ };
2254
+ }
2255
+
2256
+ function computeCoordsFromPlacement(_ref, placement, rtl) {
2257
+ let {
2258
+ reference,
2259
+ floating
2260
+ } = _ref;
2261
+ const sideAxis = getSideAxis(placement);
2262
+ const alignmentAxis = getAlignmentAxis(placement);
2263
+ const alignLength = getAxisLength(alignmentAxis);
2264
+ const side = getSide(placement);
2265
+ const isVertical = sideAxis === 'y';
2266
+ const commonX = reference.x + reference.width / 2 - floating.width / 2;
2267
+ const commonY = reference.y + reference.height / 2 - floating.height / 2;
2268
+ const commonAlign = reference[alignLength] / 2 - floating[alignLength] / 2;
2269
+ let coords;
2270
+ switch (side) {
2271
+ case 'top':
2272
+ coords = {
2273
+ x: commonX,
2274
+ y: reference.y - floating.height
2275
+ };
2276
+ break;
2277
+ case 'bottom':
2278
+ coords = {
2279
+ x: commonX,
2280
+ y: reference.y + reference.height
2281
+ };
2282
+ break;
2283
+ case 'right':
2284
+ coords = {
2285
+ x: reference.x + reference.width,
2286
+ y: commonY
2287
+ };
2288
+ break;
2289
+ case 'left':
2290
+ coords = {
2291
+ x: reference.x - floating.width,
2292
+ y: commonY
2293
+ };
2294
+ break;
2295
+ default:
2296
+ coords = {
2297
+ x: reference.x,
2298
+ y: reference.y
2299
+ };
2300
+ }
2301
+ switch (getAlignment(placement)) {
2302
+ case 'start':
2303
+ coords[alignmentAxis] -= commonAlign * (rtl && isVertical ? -1 : 1);
2304
+ break;
2305
+ case 'end':
2306
+ coords[alignmentAxis] += commonAlign * (rtl && isVertical ? -1 : 1);
2307
+ break;
2308
+ }
2309
+ return coords;
2310
+ }
2311
+
2312
+ /**
2313
+ * Resolves with an object of overflow side offsets that determine how much the
2314
+ * element is overflowing a given clipping boundary on each side.
2315
+ * - positive = overflowing the boundary by that number of pixels
2316
+ * - negative = how many pixels left before it will overflow
2317
+ * - 0 = lies flush with the boundary
2318
+ * @see https://floating-ui.com/docs/detectOverflow
2319
+ */
2320
+ async function detectOverflow(state, options) {
2321
+ var _await$platform$isEle;
2322
+ if (options === void 0) {
2323
+ options = {};
2324
+ }
2325
+ const {
2326
+ x,
2327
+ y,
2328
+ platform,
2329
+ rects,
2330
+ elements,
2331
+ strategy
2332
+ } = state;
2333
+ const {
2334
+ boundary = 'clippingAncestors',
2335
+ rootBoundary = 'viewport',
2336
+ elementContext = 'floating',
2337
+ altBoundary = false,
2338
+ padding = 0
2339
+ } = evaluate(options, state);
2340
+ const paddingObject = getPaddingObject(padding);
2341
+ const altContext = elementContext === 'floating' ? 'reference' : 'floating';
2342
+ const element = elements[altBoundary ? altContext : elementContext];
2343
+ const clippingClientRect = rectToClientRect(await platform.getClippingRect({
2344
+ element: ((_await$platform$isEle = await (platform.isElement == null ? void 0 : platform.isElement(element))) != null ? _await$platform$isEle : true) ? element : element.contextElement || (await (platform.getDocumentElement == null ? void 0 : platform.getDocumentElement(elements.floating))),
2345
+ boundary,
2346
+ rootBoundary,
2347
+ strategy
2348
+ }));
2349
+ const rect = elementContext === 'floating' ? {
2350
+ x,
2351
+ y,
2352
+ width: rects.floating.width,
2353
+ height: rects.floating.height
2354
+ } : rects.reference;
2355
+ const offsetParent = await (platform.getOffsetParent == null ? void 0 : platform.getOffsetParent(elements.floating));
2356
+ const offsetScale = (await (platform.isElement == null ? void 0 : platform.isElement(offsetParent))) ? (await (platform.getScale == null ? void 0 : platform.getScale(offsetParent))) || {
2357
+ x: 1,
2358
+ y: 1
2359
+ } : {
2360
+ x: 1,
2361
+ y: 1
2362
+ };
2363
+ const elementClientRect = rectToClientRect(platform.convertOffsetParentRelativeRectToViewportRelativeRect ? await platform.convertOffsetParentRelativeRectToViewportRelativeRect({
2364
+ elements,
2365
+ rect,
2366
+ offsetParent,
2367
+ strategy
2368
+ }) : rect);
2369
+ return {
2370
+ top: (clippingClientRect.top - elementClientRect.top + paddingObject.top) / offsetScale.y,
2371
+ bottom: (elementClientRect.bottom - clippingClientRect.bottom + paddingObject.bottom) / offsetScale.y,
2372
+ left: (clippingClientRect.left - elementClientRect.left + paddingObject.left) / offsetScale.x,
2373
+ right: (elementClientRect.right - clippingClientRect.right + paddingObject.right) / offsetScale.x
2374
+ };
2375
+ }
2376
+
2377
+ // Maximum number of resets that can occur before bailing to avoid infinite reset loops.
2378
+ const MAX_RESET_COUNT = 50;
2379
+
2380
+ /**
2381
+ * Computes the `x` and `y` coordinates that will place the floating element
2382
+ * next to a given reference element.
2383
+ *
2384
+ * This export does not have any `platform` interface logic. You will need to
2385
+ * write one for the platform you are using Floating UI with.
2386
+ */
2387
+ const computePosition$1 = async (reference, floating, config) => {
2388
+ const {
2389
+ placement = 'bottom',
2390
+ strategy = 'absolute',
2391
+ middleware = [],
2392
+ platform
2393
+ } = config;
2394
+ const platformWithDetectOverflow = platform.detectOverflow ? platform : {
2395
+ ...platform,
2396
+ detectOverflow
2397
+ };
2398
+ const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(floating));
2399
+ let rects = await platform.getElementRects({
2400
+ reference,
2401
+ floating,
2402
+ strategy
2403
+ });
2404
+ let {
2405
+ x,
2406
+ y
2407
+ } = computeCoordsFromPlacement(rects, placement, rtl);
2408
+ let statefulPlacement = placement;
2409
+ let resetCount = 0;
2410
+ const middlewareData = {};
2411
+ for (let i = 0; i < middleware.length; i++) {
2412
+ const currentMiddleware = middleware[i];
2413
+ if (!currentMiddleware) {
2414
+ continue;
2415
+ }
2416
+ const {
2417
+ name,
2418
+ fn
2419
+ } = currentMiddleware;
2420
+ const {
2421
+ x: nextX,
2422
+ y: nextY,
2423
+ data,
2424
+ reset
2425
+ } = await fn({
2426
+ x,
2427
+ y,
2428
+ initialPlacement: placement,
2429
+ placement: statefulPlacement,
2430
+ strategy,
2431
+ middlewareData,
2432
+ rects,
2433
+ platform: platformWithDetectOverflow,
2434
+ elements: {
2435
+ reference,
2436
+ floating
2437
+ }
2438
+ });
2439
+ x = nextX != null ? nextX : x;
2440
+ y = nextY != null ? nextY : y;
2441
+ middlewareData[name] = {
2442
+ ...middlewareData[name],
2443
+ ...data
2444
+ };
2445
+ if (reset && resetCount < MAX_RESET_COUNT) {
2446
+ resetCount++;
2447
+ if (typeof reset === 'object') {
2448
+ if (reset.placement) {
2449
+ statefulPlacement = reset.placement;
2450
+ }
2451
+ if (reset.rects) {
2452
+ rects = reset.rects === true ? await platform.getElementRects({
2453
+ reference,
2454
+ floating,
2455
+ strategy
2456
+ }) : reset.rects;
2457
+ }
2458
+ ({
2459
+ x,
2460
+ y
2461
+ } = computeCoordsFromPlacement(rects, statefulPlacement, rtl));
2462
+ }
2463
+ i = -1;
2464
+ }
2465
+ }
2466
+ return {
2467
+ x,
2468
+ y,
2469
+ placement: statefulPlacement,
2470
+ strategy,
2471
+ middlewareData
2472
+ };
2473
+ };
2474
+
2475
+ /**
2476
+ * Provides data to position an inner element of the floating element so that it
2477
+ * appears centered to the reference element.
2478
+ * @see https://floating-ui.com/docs/arrow
2479
+ */
2480
+ const arrow$3 = options => ({
2481
+ name: 'arrow',
2482
+ options,
2483
+ async fn(state) {
2484
+ const {
2485
+ x,
2486
+ y,
2487
+ placement,
2488
+ rects,
2489
+ platform,
2490
+ elements,
2491
+ middlewareData
2492
+ } = state;
2493
+ // Since `element` is required, we don't Partial<> the type.
2494
+ const {
2495
+ element,
2496
+ padding = 0
2497
+ } = evaluate(options, state) || {};
2498
+ if (element == null) {
2499
+ return {};
2500
+ }
2501
+ const paddingObject = getPaddingObject(padding);
2502
+ const coords = {
2503
+ x,
2504
+ y
2505
+ };
2506
+ const axis = getAlignmentAxis(placement);
2507
+ const length = getAxisLength(axis);
2508
+ const arrowDimensions = await platform.getDimensions(element);
2509
+ const isYAxis = axis === 'y';
2510
+ const minProp = isYAxis ? 'top' : 'left';
2511
+ const maxProp = isYAxis ? 'bottom' : 'right';
2512
+ const clientProp = isYAxis ? 'clientHeight' : 'clientWidth';
2513
+ const endDiff = rects.reference[length] + rects.reference[axis] - coords[axis] - rects.floating[length];
2514
+ const startDiff = coords[axis] - rects.reference[axis];
2515
+ const arrowOffsetParent = await (platform.getOffsetParent == null ? void 0 : platform.getOffsetParent(element));
2516
+ let clientSize = arrowOffsetParent ? arrowOffsetParent[clientProp] : 0;
2517
+
2518
+ // DOM platform can return `window` as the `offsetParent`.
2519
+ if (!clientSize || !(await (platform.isElement == null ? void 0 : platform.isElement(arrowOffsetParent)))) {
2520
+ clientSize = elements.floating[clientProp] || rects.floating[length];
2521
+ }
2522
+ const centerToReference = endDiff / 2 - startDiff / 2;
2523
+
2524
+ // If the padding is large enough that it causes the arrow to no longer be
2525
+ // centered, modify the padding so that it is centered.
2526
+ const largestPossiblePadding = clientSize / 2 - arrowDimensions[length] / 2 - 1;
2527
+ const minPadding = min(paddingObject[minProp], largestPossiblePadding);
2528
+ const maxPadding = min(paddingObject[maxProp], largestPossiblePadding);
2529
+
2530
+ // Make sure the arrow doesn't overflow the floating element if the center
2531
+ // point is outside the floating element's bounds.
2532
+ const min$1 = minPadding;
2533
+ const max = clientSize - arrowDimensions[length] - maxPadding;
2534
+ const center = clientSize / 2 - arrowDimensions[length] / 2 + centerToReference;
2535
+ const offset = clamp(min$1, center, max);
2536
+
2537
+ // If the reference is small enough that the arrow's padding causes it to
2538
+ // to point to nothing for an aligned placement, adjust the offset of the
2539
+ // floating element itself. To ensure `shift()` continues to take action,
2540
+ // a single reset is performed when this is true.
2541
+ const shouldAddOffset = !middlewareData.arrow && getAlignment(placement) != null && center !== offset && rects.reference[length] / 2 - (center < min$1 ? minPadding : maxPadding) - arrowDimensions[length] / 2 < 0;
2542
+ const alignmentOffset = shouldAddOffset ? center < min$1 ? center - min$1 : center - max : 0;
2543
+ return {
2544
+ [axis]: coords[axis] + alignmentOffset,
2545
+ data: {
2546
+ [axis]: offset,
2547
+ centerOffset: center - offset - alignmentOffset,
2548
+ ...(shouldAddOffset && {
2549
+ alignmentOffset
2550
+ })
2551
+ },
2552
+ reset: shouldAddOffset
2553
+ };
2554
+ }
1971
2555
  });
1972
- const Tooltip = React.forwardRef(({ children, heading, description, placement = "top", showArrow = true, className, delay = 200, disabled = false, }, ref) => {
1973
- const [isVisible, setIsVisible] = React.useState(false);
1974
- const [position, setPosition] = React.useState({ top: 0, left: 0 });
1975
- const [arrowPosition, setArrowPosition] = React.useState({ left: 0 });
1976
- const [actualPlacement, setActualPlacement] = React.useState(placement);
1977
- const timeoutRef = React.useRef(null);
1978
- const triggerRef = React.useRef(null);
1979
- const tooltipRef = React.useRef(null);
1980
- const calculatePosition = React.useCallback(() => {
1981
- if (!triggerRef.current || !tooltipRef.current)
1982
- return;
1983
- const triggerRect = triggerRef.current.getBoundingClientRect();
1984
- const tooltipRect = tooltipRef.current.getBoundingClientRect();
1985
- const gap = 8; // 8px gap between trigger and tooltip
1986
- const arrowSize = 6; // Size of the arrow
1987
- const viewportPadding = 8; // Minimum padding from viewport edges
1988
- let top = 0;
1989
- let left = 0;
1990
- let currentPlacement = placement;
1991
- // Calculate initial position based on placement
1992
- switch (placement) {
1993
- case "top-start":
1994
- top = triggerRect.top - tooltipRect.height - gap - arrowSize;
1995
- left = triggerRect.left;
1996
- break;
1997
- case "top":
1998
- top = triggerRect.top - tooltipRect.height - gap - arrowSize;
1999
- left =
2000
- triggerRect.left + triggerRect.width / 2 - tooltipRect.width / 2;
2001
- break;
2002
- case "top-end":
2003
- top = triggerRect.top - tooltipRect.height - gap - arrowSize;
2004
- left = triggerRect.right - tooltipRect.width;
2005
- break;
2006
- case "bottom-start":
2007
- top = triggerRect.bottom + gap + arrowSize;
2008
- left = triggerRect.left;
2009
- break;
2010
- case "bottom":
2011
- top = triggerRect.bottom + gap + arrowSize;
2012
- left =
2013
- triggerRect.left + triggerRect.width / 2 - tooltipRect.width / 2;
2014
- break;
2015
- case "bottom-end":
2016
- top = triggerRect.bottom + gap + arrowSize;
2017
- left = triggerRect.right - tooltipRect.width;
2018
- break;
2019
- }
2020
- // Get viewport dimensions
2021
- const viewportWidth = window.innerWidth;
2022
- const viewportHeight = window.innerHeight;
2023
- // Adjust horizontal position to keep tooltip within viewport
2024
- if (left < viewportPadding) {
2025
- // Tooltip would overflow on the left
2026
- left = viewportPadding;
2027
- }
2028
- else if (left + tooltipRect.width > viewportWidth - viewportPadding) {
2029
- // Tooltip would overflow on the right
2030
- left = viewportWidth - tooltipRect.width - viewportPadding;
2031
- }
2032
- // Adjust vertical position to keep tooltip within viewport
2033
- if (top < viewportPadding) {
2034
- // Tooltip would overflow at the top
2035
- // Try to flip to bottom if there's more space there
2036
- const spaceBelow = viewportHeight - triggerRect.bottom;
2037
- const spaceAbove = triggerRect.top;
2038
- if (spaceBelow > spaceAbove) {
2039
- // Flip to bottom
2040
- top = triggerRect.bottom + gap + arrowSize;
2041
- // Update placement to reflect the flip
2042
- if (placement === "top-start")
2043
- currentPlacement = "bottom-start";
2044
- else if (placement === "top")
2045
- currentPlacement = "bottom";
2046
- else if (placement === "top-end")
2047
- currentPlacement = "bottom-end";
2048
- }
2049
- else {
2050
- // Keep at top but adjust to stay in viewport
2051
- top = viewportPadding;
2052
- }
2556
+
2557
+ /**
2558
+ * Optimizes the visibility of the floating element by flipping the `placement`
2559
+ * in order to keep it in view when the preferred placement(s) will overflow the
2560
+ * clipping boundary. Alternative to `autoPlacement`.
2561
+ * @see https://floating-ui.com/docs/flip
2562
+ */
2563
+ const flip$2 = function (options) {
2564
+ if (options === void 0) {
2565
+ options = {};
2566
+ }
2567
+ return {
2568
+ name: 'flip',
2569
+ options,
2570
+ async fn(state) {
2571
+ var _middlewareData$arrow, _middlewareData$flip;
2572
+ const {
2573
+ placement,
2574
+ middlewareData,
2575
+ rects,
2576
+ initialPlacement,
2577
+ platform,
2578
+ elements
2579
+ } = state;
2580
+ const {
2581
+ mainAxis: checkMainAxis = true,
2582
+ crossAxis: checkCrossAxis = true,
2583
+ fallbackPlacements: specifiedFallbackPlacements,
2584
+ fallbackStrategy = 'bestFit',
2585
+ fallbackAxisSideDirection = 'none',
2586
+ flipAlignment = true,
2587
+ ...detectOverflowOptions
2588
+ } = evaluate(options, state);
2589
+
2590
+ // If a reset by the arrow was caused due to an alignment offset being
2591
+ // added, we should skip any logic now since `flip()` has already done its
2592
+ // work.
2593
+ // https://github.com/floating-ui/floating-ui/issues/2549#issuecomment-1719601643
2594
+ if ((_middlewareData$arrow = middlewareData.arrow) != null && _middlewareData$arrow.alignmentOffset) {
2595
+ return {};
2596
+ }
2597
+ const side = getSide(placement);
2598
+ const initialSideAxis = getSideAxis(initialPlacement);
2599
+ const isBasePlacement = getSide(initialPlacement) === initialPlacement;
2600
+ const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating));
2601
+ const fallbackPlacements = specifiedFallbackPlacements || (isBasePlacement || !flipAlignment ? [getOppositePlacement(initialPlacement)] : getExpandedPlacements(initialPlacement));
2602
+ const hasFallbackAxisSideDirection = fallbackAxisSideDirection !== 'none';
2603
+ if (!specifiedFallbackPlacements && hasFallbackAxisSideDirection) {
2604
+ fallbackPlacements.push(...getOppositeAxisPlacements(initialPlacement, flipAlignment, fallbackAxisSideDirection, rtl));
2605
+ }
2606
+ const placements = [initialPlacement, ...fallbackPlacements];
2607
+ const overflow = await platform.detectOverflow(state, detectOverflowOptions);
2608
+ const overflows = [];
2609
+ let overflowsData = ((_middlewareData$flip = middlewareData.flip) == null ? void 0 : _middlewareData$flip.overflows) || [];
2610
+ if (checkMainAxis) {
2611
+ overflows.push(overflow[side]);
2612
+ }
2613
+ if (checkCrossAxis) {
2614
+ const sides = getAlignmentSides(placement, rects, rtl);
2615
+ overflows.push(overflow[sides[0]], overflow[sides[1]]);
2616
+ }
2617
+ overflowsData = [...overflowsData, {
2618
+ placement,
2619
+ overflows
2620
+ }];
2621
+
2622
+ // One or more sides is overflowing.
2623
+ if (!overflows.every(side => side <= 0)) {
2624
+ var _middlewareData$flip2, _overflowsData$filter;
2625
+ const nextIndex = (((_middlewareData$flip2 = middlewareData.flip) == null ? void 0 : _middlewareData$flip2.index) || 0) + 1;
2626
+ const nextPlacement = placements[nextIndex];
2627
+ if (nextPlacement) {
2628
+ const ignoreCrossAxisOverflow = checkCrossAxis === 'alignment' ? initialSideAxis !== getSideAxis(nextPlacement) : false;
2629
+ if (!ignoreCrossAxisOverflow ||
2630
+ // We leave the current main axis only if every placement on that axis
2631
+ // overflows the main axis.
2632
+ overflowsData.every(d => getSideAxis(d.placement) === initialSideAxis ? d.overflows[0] > 0 : true)) {
2633
+ // Try next placement and re-run the lifecycle.
2634
+ return {
2635
+ data: {
2636
+ index: nextIndex,
2637
+ overflows: overflowsData
2638
+ },
2639
+ reset: {
2640
+ placement: nextPlacement
2641
+ }
2642
+ };
2643
+ }
2053
2644
  }
2054
- else if (top + tooltipRect.height > viewportHeight - viewportPadding) {
2055
- // Tooltip would overflow at the bottom
2056
- // Try to flip to top if there's more space there
2057
- const spaceAbove = triggerRect.top;
2058
- const spaceBelow = viewportHeight - triggerRect.bottom;
2059
- if (spaceAbove > spaceBelow) {
2060
- // Flip to top
2061
- top = triggerRect.top - tooltipRect.height - gap - arrowSize;
2062
- // Update placement to reflect the flip
2063
- if (placement === "bottom-start")
2064
- currentPlacement = "top-start";
2065
- else if (placement === "bottom")
2066
- currentPlacement = "top";
2067
- else if (placement === "bottom-end")
2068
- currentPlacement = "top-end";
2069
- }
2070
- else {
2071
- // Keep at bottom but adjust to stay in viewport
2072
- top = viewportHeight - tooltipRect.height - viewportPadding;
2645
+
2646
+ // First, find the candidates that fit on the mainAxis side of overflow,
2647
+ // then find the placement that fits the best on the main crossAxis side.
2648
+ let resetPlacement = (_overflowsData$filter = overflowsData.filter(d => d.overflows[0] <= 0).sort((a, b) => a.overflows[1] - b.overflows[1])[0]) == null ? void 0 : _overflowsData$filter.placement;
2649
+
2650
+ // Otherwise fallback.
2651
+ if (!resetPlacement) {
2652
+ switch (fallbackStrategy) {
2653
+ case 'bestFit':
2654
+ {
2655
+ var _overflowsData$filter2;
2656
+ const placement = (_overflowsData$filter2 = overflowsData.filter(d => {
2657
+ if (hasFallbackAxisSideDirection) {
2658
+ const currentSideAxis = getSideAxis(d.placement);
2659
+ return currentSideAxis === initialSideAxis ||
2660
+ // Create a bias to the `y` side axis due to horizontal
2661
+ // reading directions favoring greater width.
2662
+ currentSideAxis === 'y';
2663
+ }
2664
+ return true;
2665
+ }).map(d => [d.placement, d.overflows.filter(overflow => overflow > 0).reduce((acc, overflow) => acc + overflow, 0)]).sort((a, b) => a[1] - b[1])[0]) == null ? void 0 : _overflowsData$filter2[0];
2666
+ if (placement) {
2667
+ resetPlacement = placement;
2668
+ }
2669
+ break;
2670
+ }
2671
+ case 'initialPlacement':
2672
+ resetPlacement = initialPlacement;
2673
+ break;
2674
+ }
2675
+ }
2676
+ if (placement !== resetPlacement) {
2677
+ return {
2678
+ reset: {
2679
+ placement: resetPlacement
2073
2680
  }
2681
+ };
2074
2682
  }
2075
- // Calculate arrow position relative to trigger
2076
- // The arrow should point to the center of the trigger element
2077
- const triggerCenterX = triggerRect.left + triggerRect.width / 2;
2078
- const tooltipLeft = left;
2079
- const arrowLeft = triggerCenterX - tooltipLeft;
2080
- // Clamp arrow position to stay within tooltip bounds (with padding)
2081
- const arrowPadding = 16; // Minimum distance from tooltip edges
2082
- const clampedArrowLeft = Math.max(arrowPadding, Math.min(arrowLeft, tooltipRect.width - arrowPadding));
2083
- setPosition({ top, left });
2084
- setArrowPosition({ left: clampedArrowLeft });
2085
- setActualPlacement(currentPlacement);
2086
- }, [placement]);
2087
- const handleMouseEnter = () => {
2088
- if (disabled)
2089
- return;
2090
- if (timeoutRef.current) {
2091
- clearTimeout(timeoutRef.current);
2092
- }
2093
- timeoutRef.current = setTimeout(() => {
2094
- setIsVisible(true);
2095
- }, delay);
2683
+ }
2684
+ return {};
2685
+ }
2686
+ };
2687
+ };
2688
+
2689
+ function getSideOffsets(overflow, rect) {
2690
+ return {
2691
+ top: overflow.top - rect.height,
2692
+ right: overflow.right - rect.width,
2693
+ bottom: overflow.bottom - rect.height,
2694
+ left: overflow.left - rect.width
2695
+ };
2696
+ }
2697
+ function isAnySideFullyClipped(overflow) {
2698
+ return sides.some(side => overflow[side] >= 0);
2699
+ }
2700
+ /**
2701
+ * Provides data to hide the floating element in applicable situations, such as
2702
+ * when it is not in the same clipping context as the reference element.
2703
+ * @see https://floating-ui.com/docs/hide
2704
+ */
2705
+ const hide$2 = function (options) {
2706
+ if (options === void 0) {
2707
+ options = {};
2708
+ }
2709
+ return {
2710
+ name: 'hide',
2711
+ options,
2712
+ async fn(state) {
2713
+ const {
2714
+ rects,
2715
+ platform
2716
+ } = state;
2717
+ const {
2718
+ strategy = 'referenceHidden',
2719
+ ...detectOverflowOptions
2720
+ } = evaluate(options, state);
2721
+ switch (strategy) {
2722
+ case 'referenceHidden':
2723
+ {
2724
+ const overflow = await platform.detectOverflow(state, {
2725
+ ...detectOverflowOptions,
2726
+ elementContext: 'reference'
2727
+ });
2728
+ const offsets = getSideOffsets(overflow, rects.reference);
2729
+ return {
2730
+ data: {
2731
+ referenceHiddenOffsets: offsets,
2732
+ referenceHidden: isAnySideFullyClipped(offsets)
2733
+ }
2734
+ };
2735
+ }
2736
+ case 'escaped':
2737
+ {
2738
+ const overflow = await platform.detectOverflow(state, {
2739
+ ...detectOverflowOptions,
2740
+ altBoundary: true
2741
+ });
2742
+ const offsets = getSideOffsets(overflow, rects.floating);
2743
+ return {
2744
+ data: {
2745
+ escapedOffsets: offsets,
2746
+ escaped: isAnySideFullyClipped(offsets)
2747
+ }
2748
+ };
2749
+ }
2750
+ default:
2751
+ {
2752
+ return {};
2753
+ }
2754
+ }
2755
+ }
2756
+ };
2757
+ };
2758
+
2759
+ const originSides = /*#__PURE__*/new Set(['left', 'top']);
2760
+
2761
+ // For type backwards-compatibility, the `OffsetOptions` type was also
2762
+ // Derivable.
2763
+
2764
+ async function convertValueToCoords(state, options) {
2765
+ const {
2766
+ placement,
2767
+ platform,
2768
+ elements
2769
+ } = state;
2770
+ const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating));
2771
+ const side = getSide(placement);
2772
+ const alignment = getAlignment(placement);
2773
+ const isVertical = getSideAxis(placement) === 'y';
2774
+ const mainAxisMulti = originSides.has(side) ? -1 : 1;
2775
+ const crossAxisMulti = rtl && isVertical ? -1 : 1;
2776
+ const rawValue = evaluate(options, state);
2777
+
2778
+ // eslint-disable-next-line prefer-const
2779
+ let {
2780
+ mainAxis,
2781
+ crossAxis,
2782
+ alignmentAxis
2783
+ } = typeof rawValue === 'number' ? {
2784
+ mainAxis: rawValue,
2785
+ crossAxis: 0,
2786
+ alignmentAxis: null
2787
+ } : {
2788
+ mainAxis: rawValue.mainAxis || 0,
2789
+ crossAxis: rawValue.crossAxis || 0,
2790
+ alignmentAxis: rawValue.alignmentAxis
2791
+ };
2792
+ if (alignment && typeof alignmentAxis === 'number') {
2793
+ crossAxis = alignment === 'end' ? alignmentAxis * -1 : alignmentAxis;
2794
+ }
2795
+ return isVertical ? {
2796
+ x: crossAxis * crossAxisMulti,
2797
+ y: mainAxis * mainAxisMulti
2798
+ } : {
2799
+ x: mainAxis * mainAxisMulti,
2800
+ y: crossAxis * crossAxisMulti
2801
+ };
2802
+ }
2803
+
2804
+ /**
2805
+ * Modifies the placement by translating the floating element along the
2806
+ * specified axes.
2807
+ * A number (shorthand for `mainAxis` or distance), or an axes configuration
2808
+ * object may be passed.
2809
+ * @see https://floating-ui.com/docs/offset
2810
+ */
2811
+ const offset$2 = function (options) {
2812
+ if (options === void 0) {
2813
+ options = 0;
2814
+ }
2815
+ return {
2816
+ name: 'offset',
2817
+ options,
2818
+ async fn(state) {
2819
+ var _middlewareData$offse, _middlewareData$arrow;
2820
+ const {
2821
+ x,
2822
+ y,
2823
+ placement,
2824
+ middlewareData
2825
+ } = state;
2826
+ const diffCoords = await convertValueToCoords(state, options);
2827
+
2828
+ // If the placement is the same and the arrow caused an alignment offset
2829
+ // then we don't need to change the positioning coordinates.
2830
+ if (placement === ((_middlewareData$offse = middlewareData.offset) == null ? void 0 : _middlewareData$offse.placement) && (_middlewareData$arrow = middlewareData.arrow) != null && _middlewareData$arrow.alignmentOffset) {
2831
+ return {};
2832
+ }
2833
+ return {
2834
+ x: x + diffCoords.x,
2835
+ y: y + diffCoords.y,
2836
+ data: {
2837
+ ...diffCoords,
2838
+ placement
2839
+ }
2840
+ };
2841
+ }
2842
+ };
2843
+ };
2844
+
2845
+ /**
2846
+ * Optimizes the visibility of the floating element by shifting it in order to
2847
+ * keep it in view when it will overflow the clipping boundary.
2848
+ * @see https://floating-ui.com/docs/shift
2849
+ */
2850
+ const shift$2 = function (options) {
2851
+ if (options === void 0) {
2852
+ options = {};
2853
+ }
2854
+ return {
2855
+ name: 'shift',
2856
+ options,
2857
+ async fn(state) {
2858
+ const {
2859
+ x,
2860
+ y,
2861
+ placement,
2862
+ platform
2863
+ } = state;
2864
+ const {
2865
+ mainAxis: checkMainAxis = true,
2866
+ crossAxis: checkCrossAxis = false,
2867
+ limiter = {
2868
+ fn: _ref => {
2869
+ let {
2870
+ x,
2871
+ y
2872
+ } = _ref;
2873
+ return {
2874
+ x,
2875
+ y
2876
+ };
2877
+ }
2878
+ },
2879
+ ...detectOverflowOptions
2880
+ } = evaluate(options, state);
2881
+ const coords = {
2882
+ x,
2883
+ y
2884
+ };
2885
+ const overflow = await platform.detectOverflow(state, detectOverflowOptions);
2886
+ const crossAxis = getSideAxis(getSide(placement));
2887
+ const mainAxis = getOppositeAxis(crossAxis);
2888
+ let mainAxisCoord = coords[mainAxis];
2889
+ let crossAxisCoord = coords[crossAxis];
2890
+ if (checkMainAxis) {
2891
+ const minSide = mainAxis === 'y' ? 'top' : 'left';
2892
+ const maxSide = mainAxis === 'y' ? 'bottom' : 'right';
2893
+ const min = mainAxisCoord + overflow[minSide];
2894
+ const max = mainAxisCoord - overflow[maxSide];
2895
+ mainAxisCoord = clamp(min, mainAxisCoord, max);
2896
+ }
2897
+ if (checkCrossAxis) {
2898
+ const minSide = crossAxis === 'y' ? 'top' : 'left';
2899
+ const maxSide = crossAxis === 'y' ? 'bottom' : 'right';
2900
+ const min = crossAxisCoord + overflow[minSide];
2901
+ const max = crossAxisCoord - overflow[maxSide];
2902
+ crossAxisCoord = clamp(min, crossAxisCoord, max);
2903
+ }
2904
+ const limitedCoords = limiter.fn({
2905
+ ...state,
2906
+ [mainAxis]: mainAxisCoord,
2907
+ [crossAxis]: crossAxisCoord
2908
+ });
2909
+ return {
2910
+ ...limitedCoords,
2911
+ data: {
2912
+ x: limitedCoords.x - x,
2913
+ y: limitedCoords.y - y,
2914
+ enabled: {
2915
+ [mainAxis]: checkMainAxis,
2916
+ [crossAxis]: checkCrossAxis
2917
+ }
2918
+ }
2919
+ };
2920
+ }
2921
+ };
2922
+ };
2923
+ /**
2924
+ * Built-in `limiter` that will stop `shift()` at a certain point.
2925
+ */
2926
+ const limitShift$2 = function (options) {
2927
+ if (options === void 0) {
2928
+ options = {};
2929
+ }
2930
+ return {
2931
+ options,
2932
+ fn(state) {
2933
+ const {
2934
+ x,
2935
+ y,
2936
+ placement,
2937
+ rects,
2938
+ middlewareData
2939
+ } = state;
2940
+ const {
2941
+ offset = 0,
2942
+ mainAxis: checkMainAxis = true,
2943
+ crossAxis: checkCrossAxis = true
2944
+ } = evaluate(options, state);
2945
+ const coords = {
2946
+ x,
2947
+ y
2948
+ };
2949
+ const crossAxis = getSideAxis(placement);
2950
+ const mainAxis = getOppositeAxis(crossAxis);
2951
+ let mainAxisCoord = coords[mainAxis];
2952
+ let crossAxisCoord = coords[crossAxis];
2953
+ const rawOffset = evaluate(offset, state);
2954
+ const computedOffset = typeof rawOffset === 'number' ? {
2955
+ mainAxis: rawOffset,
2956
+ crossAxis: 0
2957
+ } : {
2958
+ mainAxis: 0,
2959
+ crossAxis: 0,
2960
+ ...rawOffset
2961
+ };
2962
+ if (checkMainAxis) {
2963
+ const len = mainAxis === 'y' ? 'height' : 'width';
2964
+ const limitMin = rects.reference[mainAxis] - rects.floating[len] + computedOffset.mainAxis;
2965
+ const limitMax = rects.reference[mainAxis] + rects.reference[len] - computedOffset.mainAxis;
2966
+ if (mainAxisCoord < limitMin) {
2967
+ mainAxisCoord = limitMin;
2968
+ } else if (mainAxisCoord > limitMax) {
2969
+ mainAxisCoord = limitMax;
2970
+ }
2971
+ }
2972
+ if (checkCrossAxis) {
2973
+ var _middlewareData$offse, _middlewareData$offse2;
2974
+ const len = mainAxis === 'y' ? 'width' : 'height';
2975
+ const isOriginSide = originSides.has(getSide(placement));
2976
+ const limitMin = rects.reference[crossAxis] - rects.floating[len] + (isOriginSide ? ((_middlewareData$offse = middlewareData.offset) == null ? void 0 : _middlewareData$offse[crossAxis]) || 0 : 0) + (isOriginSide ? 0 : computedOffset.crossAxis);
2977
+ const limitMax = rects.reference[crossAxis] + rects.reference[len] + (isOriginSide ? 0 : ((_middlewareData$offse2 = middlewareData.offset) == null ? void 0 : _middlewareData$offse2[crossAxis]) || 0) - (isOriginSide ? computedOffset.crossAxis : 0);
2978
+ if (crossAxisCoord < limitMin) {
2979
+ crossAxisCoord = limitMin;
2980
+ } else if (crossAxisCoord > limitMax) {
2981
+ crossAxisCoord = limitMax;
2982
+ }
2983
+ }
2984
+ return {
2985
+ [mainAxis]: mainAxisCoord,
2986
+ [crossAxis]: crossAxisCoord
2987
+ };
2988
+ }
2989
+ };
2990
+ };
2991
+
2992
+ /**
2993
+ * Provides data that allows you to change the size of the floating element —
2994
+ * for instance, prevent it from overflowing the clipping boundary or match the
2995
+ * width of the reference element.
2996
+ * @see https://floating-ui.com/docs/size
2997
+ */
2998
+ const size$2 = function (options) {
2999
+ if (options === void 0) {
3000
+ options = {};
3001
+ }
3002
+ return {
3003
+ name: 'size',
3004
+ options,
3005
+ async fn(state) {
3006
+ var _state$middlewareData, _state$middlewareData2;
3007
+ const {
3008
+ placement,
3009
+ rects,
3010
+ platform,
3011
+ elements
3012
+ } = state;
3013
+ const {
3014
+ apply = () => {},
3015
+ ...detectOverflowOptions
3016
+ } = evaluate(options, state);
3017
+ const overflow = await platform.detectOverflow(state, detectOverflowOptions);
3018
+ const side = getSide(placement);
3019
+ const alignment = getAlignment(placement);
3020
+ const isYAxis = getSideAxis(placement) === 'y';
3021
+ const {
3022
+ width,
3023
+ height
3024
+ } = rects.floating;
3025
+ let heightSide;
3026
+ let widthSide;
3027
+ if (side === 'top' || side === 'bottom') {
3028
+ heightSide = side;
3029
+ widthSide = alignment === ((await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating))) ? 'start' : 'end') ? 'left' : 'right';
3030
+ } else {
3031
+ widthSide = side;
3032
+ heightSide = alignment === 'end' ? 'top' : 'bottom';
3033
+ }
3034
+ const maximumClippingHeight = height - overflow.top - overflow.bottom;
3035
+ const maximumClippingWidth = width - overflow.left - overflow.right;
3036
+ const overflowAvailableHeight = min(height - overflow[heightSide], maximumClippingHeight);
3037
+ const overflowAvailableWidth = min(width - overflow[widthSide], maximumClippingWidth);
3038
+ const noShift = !state.middlewareData.shift;
3039
+ let availableHeight = overflowAvailableHeight;
3040
+ let availableWidth = overflowAvailableWidth;
3041
+ if ((_state$middlewareData = state.middlewareData.shift) != null && _state$middlewareData.enabled.x) {
3042
+ availableWidth = maximumClippingWidth;
3043
+ }
3044
+ if ((_state$middlewareData2 = state.middlewareData.shift) != null && _state$middlewareData2.enabled.y) {
3045
+ availableHeight = maximumClippingHeight;
3046
+ }
3047
+ if (noShift && !alignment) {
3048
+ const xMin = max(overflow.left, 0);
3049
+ const xMax = max(overflow.right, 0);
3050
+ const yMin = max(overflow.top, 0);
3051
+ const yMax = max(overflow.bottom, 0);
3052
+ if (isYAxis) {
3053
+ availableWidth = width - 2 * (xMin !== 0 || xMax !== 0 ? xMin + xMax : max(overflow.left, overflow.right));
3054
+ } else {
3055
+ availableHeight = height - 2 * (yMin !== 0 || yMax !== 0 ? yMin + yMax : max(overflow.top, overflow.bottom));
3056
+ }
3057
+ }
3058
+ await apply({
3059
+ ...state,
3060
+ availableWidth,
3061
+ availableHeight
3062
+ });
3063
+ const nextDimensions = await platform.getDimensions(elements.floating);
3064
+ if (width !== nextDimensions.width || height !== nextDimensions.height) {
3065
+ return {
3066
+ reset: {
3067
+ rects: true
3068
+ }
3069
+ };
3070
+ }
3071
+ return {};
3072
+ }
3073
+ };
3074
+ };
3075
+
3076
+ function hasWindow() {
3077
+ return typeof window !== 'undefined';
3078
+ }
3079
+ function getNodeName(node) {
3080
+ if (isNode(node)) {
3081
+ return (node.nodeName || '').toLowerCase();
3082
+ }
3083
+ // Mocked nodes in testing environments may not be instances of Node. By
3084
+ // returning `#document` an infinite loop won't occur.
3085
+ // https://github.com/floating-ui/floating-ui/issues/2317
3086
+ return '#document';
3087
+ }
3088
+ function getWindow(node) {
3089
+ var _node$ownerDocument;
3090
+ return (node == null || (_node$ownerDocument = node.ownerDocument) == null ? void 0 : _node$ownerDocument.defaultView) || window;
3091
+ }
3092
+ function getDocumentElement(node) {
3093
+ var _ref;
3094
+ return (_ref = (isNode(node) ? node.ownerDocument : node.document) || window.document) == null ? void 0 : _ref.documentElement;
3095
+ }
3096
+ function isNode(value) {
3097
+ if (!hasWindow()) {
3098
+ return false;
3099
+ }
3100
+ return value instanceof Node || value instanceof getWindow(value).Node;
3101
+ }
3102
+ function isElement(value) {
3103
+ if (!hasWindow()) {
3104
+ return false;
3105
+ }
3106
+ return value instanceof Element || value instanceof getWindow(value).Element;
3107
+ }
3108
+ function isHTMLElement(value) {
3109
+ if (!hasWindow()) {
3110
+ return false;
3111
+ }
3112
+ return value instanceof HTMLElement || value instanceof getWindow(value).HTMLElement;
3113
+ }
3114
+ function isShadowRoot(value) {
3115
+ if (!hasWindow() || typeof ShadowRoot === 'undefined') {
3116
+ return false;
3117
+ }
3118
+ return value instanceof ShadowRoot || value instanceof getWindow(value).ShadowRoot;
3119
+ }
3120
+ function isOverflowElement(element) {
3121
+ const {
3122
+ overflow,
3123
+ overflowX,
3124
+ overflowY,
3125
+ display
3126
+ } = getComputedStyle$1(element);
3127
+ return /auto|scroll|overlay|hidden|clip/.test(overflow + overflowY + overflowX) && display !== 'inline' && display !== 'contents';
3128
+ }
3129
+ function isTableElement(element) {
3130
+ return /^(table|td|th)$/.test(getNodeName(element));
3131
+ }
3132
+ function isTopLayer(element) {
3133
+ try {
3134
+ if (element.matches(':popover-open')) {
3135
+ return true;
3136
+ }
3137
+ } catch (_e) {
3138
+ // no-op
3139
+ }
3140
+ try {
3141
+ return element.matches(':modal');
3142
+ } catch (_e) {
3143
+ return false;
3144
+ }
3145
+ }
3146
+ const willChangeRe = /transform|translate|scale|rotate|perspective|filter/;
3147
+ const containRe = /paint|layout|strict|content/;
3148
+ const isNotNone = value => !!value && value !== 'none';
3149
+ let isWebKitValue;
3150
+ function isContainingBlock(elementOrCss) {
3151
+ const css = isElement(elementOrCss) ? getComputedStyle$1(elementOrCss) : elementOrCss;
3152
+
3153
+ // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block
3154
+ // https://drafts.csswg.org/css-transforms-2/#individual-transforms
3155
+ return isNotNone(css.transform) || isNotNone(css.translate) || isNotNone(css.scale) || isNotNone(css.rotate) || isNotNone(css.perspective) || !isWebKit() && (isNotNone(css.backdropFilter) || isNotNone(css.filter)) || willChangeRe.test(css.willChange || '') || containRe.test(css.contain || '');
3156
+ }
3157
+ function getContainingBlock(element) {
3158
+ let currentNode = getParentNode(element);
3159
+ while (isHTMLElement(currentNode) && !isLastTraversableNode(currentNode)) {
3160
+ if (isContainingBlock(currentNode)) {
3161
+ return currentNode;
3162
+ } else if (isTopLayer(currentNode)) {
3163
+ return null;
3164
+ }
3165
+ currentNode = getParentNode(currentNode);
3166
+ }
3167
+ return null;
3168
+ }
3169
+ function isWebKit() {
3170
+ if (isWebKitValue == null) {
3171
+ isWebKitValue = typeof CSS !== 'undefined' && CSS.supports && CSS.supports('-webkit-backdrop-filter', 'none');
3172
+ }
3173
+ return isWebKitValue;
3174
+ }
3175
+ function isLastTraversableNode(node) {
3176
+ return /^(html|body|#document)$/.test(getNodeName(node));
3177
+ }
3178
+ function getComputedStyle$1(element) {
3179
+ return getWindow(element).getComputedStyle(element);
3180
+ }
3181
+ function getNodeScroll(element) {
3182
+ if (isElement(element)) {
3183
+ return {
3184
+ scrollLeft: element.scrollLeft,
3185
+ scrollTop: element.scrollTop
2096
3186
  };
2097
- const handleMouseLeave = () => {
2098
- if (timeoutRef.current) {
2099
- clearTimeout(timeoutRef.current);
2100
- }
2101
- setIsVisible(false);
3187
+ }
3188
+ return {
3189
+ scrollLeft: element.scrollX,
3190
+ scrollTop: element.scrollY
3191
+ };
3192
+ }
3193
+ function getParentNode(node) {
3194
+ if (getNodeName(node) === 'html') {
3195
+ return node;
3196
+ }
3197
+ const result =
3198
+ // Step into the shadow DOM of the parent of a slotted node.
3199
+ node.assignedSlot ||
3200
+ // DOM Element detected.
3201
+ node.parentNode ||
3202
+ // ShadowRoot detected.
3203
+ isShadowRoot(node) && node.host ||
3204
+ // Fallback.
3205
+ getDocumentElement(node);
3206
+ return isShadowRoot(result) ? result.host : result;
3207
+ }
3208
+ function getNearestOverflowAncestor(node) {
3209
+ const parentNode = getParentNode(node);
3210
+ if (isLastTraversableNode(parentNode)) {
3211
+ return node.ownerDocument ? node.ownerDocument.body : node.body;
3212
+ }
3213
+ if (isHTMLElement(parentNode) && isOverflowElement(parentNode)) {
3214
+ return parentNode;
3215
+ }
3216
+ return getNearestOverflowAncestor(parentNode);
3217
+ }
3218
+ function getOverflowAncestors(node, list, traverseIframes) {
3219
+ var _node$ownerDocument2;
3220
+ if (list === void 0) {
3221
+ list = [];
3222
+ }
3223
+ if (traverseIframes === void 0) {
3224
+ traverseIframes = true;
3225
+ }
3226
+ const scrollableAncestor = getNearestOverflowAncestor(node);
3227
+ const isBody = scrollableAncestor === ((_node$ownerDocument2 = node.ownerDocument) == null ? void 0 : _node$ownerDocument2.body);
3228
+ const win = getWindow(scrollableAncestor);
3229
+ if (isBody) {
3230
+ const frameElement = getFrameElement(win);
3231
+ return list.concat(win, win.visualViewport || [], isOverflowElement(scrollableAncestor) ? scrollableAncestor : [], frameElement && traverseIframes ? getOverflowAncestors(frameElement) : []);
3232
+ } else {
3233
+ return list.concat(scrollableAncestor, getOverflowAncestors(scrollableAncestor, [], traverseIframes));
3234
+ }
3235
+ }
3236
+ function getFrameElement(win) {
3237
+ return win.parent && Object.getPrototypeOf(win.parent) ? win.frameElement : null;
3238
+ }
3239
+
3240
+ function getCssDimensions(element) {
3241
+ const css = getComputedStyle$1(element);
3242
+ // In testing environments, the `width` and `height` properties are empty
3243
+ // strings for SVG elements, returning NaN. Fallback to `0` in this case.
3244
+ let width = parseFloat(css.width) || 0;
3245
+ let height = parseFloat(css.height) || 0;
3246
+ const hasOffset = isHTMLElement(element);
3247
+ const offsetWidth = hasOffset ? element.offsetWidth : width;
3248
+ const offsetHeight = hasOffset ? element.offsetHeight : height;
3249
+ const shouldFallback = round(width) !== offsetWidth || round(height) !== offsetHeight;
3250
+ if (shouldFallback) {
3251
+ width = offsetWidth;
3252
+ height = offsetHeight;
3253
+ }
3254
+ return {
3255
+ width,
3256
+ height,
3257
+ $: shouldFallback
3258
+ };
3259
+ }
3260
+
3261
+ function unwrapElement(element) {
3262
+ return !isElement(element) ? element.contextElement : element;
3263
+ }
3264
+
3265
+ function getScale(element) {
3266
+ const domElement = unwrapElement(element);
3267
+ if (!isHTMLElement(domElement)) {
3268
+ return createCoords(1);
3269
+ }
3270
+ const rect = domElement.getBoundingClientRect();
3271
+ const {
3272
+ width,
3273
+ height,
3274
+ $
3275
+ } = getCssDimensions(domElement);
3276
+ let x = ($ ? round(rect.width) : rect.width) / width;
3277
+ let y = ($ ? round(rect.height) : rect.height) / height;
3278
+
3279
+ // 0, NaN, or Infinity should always fallback to 1.
3280
+
3281
+ if (!x || !Number.isFinite(x)) {
3282
+ x = 1;
3283
+ }
3284
+ if (!y || !Number.isFinite(y)) {
3285
+ y = 1;
3286
+ }
3287
+ return {
3288
+ x,
3289
+ y
3290
+ };
3291
+ }
3292
+
3293
+ const noOffsets = /*#__PURE__*/createCoords(0);
3294
+ function getVisualOffsets(element) {
3295
+ const win = getWindow(element);
3296
+ if (!isWebKit() || !win.visualViewport) {
3297
+ return noOffsets;
3298
+ }
3299
+ return {
3300
+ x: win.visualViewport.offsetLeft,
3301
+ y: win.visualViewport.offsetTop
3302
+ };
3303
+ }
3304
+ function shouldAddVisualOffsets(element, isFixed, floatingOffsetParent) {
3305
+ if (isFixed === void 0) {
3306
+ isFixed = false;
3307
+ }
3308
+ if (!floatingOffsetParent || isFixed && floatingOffsetParent !== getWindow(element)) {
3309
+ return false;
3310
+ }
3311
+ return isFixed;
3312
+ }
3313
+
3314
+ function getBoundingClientRect(element, includeScale, isFixedStrategy, offsetParent) {
3315
+ if (includeScale === void 0) {
3316
+ includeScale = false;
3317
+ }
3318
+ if (isFixedStrategy === void 0) {
3319
+ isFixedStrategy = false;
3320
+ }
3321
+ const clientRect = element.getBoundingClientRect();
3322
+ const domElement = unwrapElement(element);
3323
+ let scale = createCoords(1);
3324
+ if (includeScale) {
3325
+ if (offsetParent) {
3326
+ if (isElement(offsetParent)) {
3327
+ scale = getScale(offsetParent);
3328
+ }
3329
+ } else {
3330
+ scale = getScale(element);
3331
+ }
3332
+ }
3333
+ const visualOffsets = shouldAddVisualOffsets(domElement, isFixedStrategy, offsetParent) ? getVisualOffsets(domElement) : createCoords(0);
3334
+ let x = (clientRect.left + visualOffsets.x) / scale.x;
3335
+ let y = (clientRect.top + visualOffsets.y) / scale.y;
3336
+ let width = clientRect.width / scale.x;
3337
+ let height = clientRect.height / scale.y;
3338
+ if (domElement) {
3339
+ const win = getWindow(domElement);
3340
+ const offsetWin = offsetParent && isElement(offsetParent) ? getWindow(offsetParent) : offsetParent;
3341
+ let currentWin = win;
3342
+ let currentIFrame = getFrameElement(currentWin);
3343
+ while (currentIFrame && offsetParent && offsetWin !== currentWin) {
3344
+ const iframeScale = getScale(currentIFrame);
3345
+ const iframeRect = currentIFrame.getBoundingClientRect();
3346
+ const css = getComputedStyle$1(currentIFrame);
3347
+ const left = iframeRect.left + (currentIFrame.clientLeft + parseFloat(css.paddingLeft)) * iframeScale.x;
3348
+ const top = iframeRect.top + (currentIFrame.clientTop + parseFloat(css.paddingTop)) * iframeScale.y;
3349
+ x *= iframeScale.x;
3350
+ y *= iframeScale.y;
3351
+ width *= iframeScale.x;
3352
+ height *= iframeScale.y;
3353
+ x += left;
3354
+ y += top;
3355
+ currentWin = getWindow(currentIFrame);
3356
+ currentIFrame = getFrameElement(currentWin);
3357
+ }
3358
+ }
3359
+ return rectToClientRect({
3360
+ width,
3361
+ height,
3362
+ x,
3363
+ y
3364
+ });
3365
+ }
3366
+
3367
+ // If <html> has a CSS width greater than the viewport, then this will be
3368
+ // incorrect for RTL.
3369
+ function getWindowScrollBarX(element, rect) {
3370
+ const leftScroll = getNodeScroll(element).scrollLeft;
3371
+ if (!rect) {
3372
+ return getBoundingClientRect(getDocumentElement(element)).left + leftScroll;
3373
+ }
3374
+ return rect.left + leftScroll;
3375
+ }
3376
+
3377
+ function getHTMLOffset(documentElement, scroll) {
3378
+ const htmlRect = documentElement.getBoundingClientRect();
3379
+ const x = htmlRect.left + scroll.scrollLeft - getWindowScrollBarX(documentElement, htmlRect);
3380
+ const y = htmlRect.top + scroll.scrollTop;
3381
+ return {
3382
+ x,
3383
+ y
3384
+ };
3385
+ }
3386
+
3387
+ function convertOffsetParentRelativeRectToViewportRelativeRect(_ref) {
3388
+ let {
3389
+ elements,
3390
+ rect,
3391
+ offsetParent,
3392
+ strategy
3393
+ } = _ref;
3394
+ const isFixed = strategy === 'fixed';
3395
+ const documentElement = getDocumentElement(offsetParent);
3396
+ const topLayer = elements ? isTopLayer(elements.floating) : false;
3397
+ if (offsetParent === documentElement || topLayer && isFixed) {
3398
+ return rect;
3399
+ }
3400
+ let scroll = {
3401
+ scrollLeft: 0,
3402
+ scrollTop: 0
3403
+ };
3404
+ let scale = createCoords(1);
3405
+ const offsets = createCoords(0);
3406
+ const isOffsetParentAnElement = isHTMLElement(offsetParent);
3407
+ if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {
3408
+ if (getNodeName(offsetParent) !== 'body' || isOverflowElement(documentElement)) {
3409
+ scroll = getNodeScroll(offsetParent);
3410
+ }
3411
+ if (isOffsetParentAnElement) {
3412
+ const offsetRect = getBoundingClientRect(offsetParent);
3413
+ scale = getScale(offsetParent);
3414
+ offsets.x = offsetRect.x + offsetParent.clientLeft;
3415
+ offsets.y = offsetRect.y + offsetParent.clientTop;
3416
+ }
3417
+ }
3418
+ const htmlOffset = documentElement && !isOffsetParentAnElement && !isFixed ? getHTMLOffset(documentElement, scroll) : createCoords(0);
3419
+ return {
3420
+ width: rect.width * scale.x,
3421
+ height: rect.height * scale.y,
3422
+ x: rect.x * scale.x - scroll.scrollLeft * scale.x + offsets.x + htmlOffset.x,
3423
+ y: rect.y * scale.y - scroll.scrollTop * scale.y + offsets.y + htmlOffset.y
3424
+ };
3425
+ }
3426
+
3427
+ function getClientRects(element) {
3428
+ return Array.from(element.getClientRects());
3429
+ }
3430
+
3431
+ // Gets the entire size of the scrollable document area, even extending outside
3432
+ // of the `<html>` and `<body>` rect bounds if horizontally scrollable.
3433
+ function getDocumentRect(element) {
3434
+ const html = getDocumentElement(element);
3435
+ const scroll = getNodeScroll(element);
3436
+ const body = element.ownerDocument.body;
3437
+ const width = max(html.scrollWidth, html.clientWidth, body.scrollWidth, body.clientWidth);
3438
+ const height = max(html.scrollHeight, html.clientHeight, body.scrollHeight, body.clientHeight);
3439
+ let x = -scroll.scrollLeft + getWindowScrollBarX(element);
3440
+ const y = -scroll.scrollTop;
3441
+ if (getComputedStyle$1(body).direction === 'rtl') {
3442
+ x += max(html.clientWidth, body.clientWidth) - width;
3443
+ }
3444
+ return {
3445
+ width,
3446
+ height,
3447
+ x,
3448
+ y
3449
+ };
3450
+ }
3451
+
3452
+ // Safety check: ensure the scrollbar space is reasonable in case this
3453
+ // calculation is affected by unusual styles.
3454
+ // Most scrollbars leave 15-18px of space.
3455
+ const SCROLLBAR_MAX = 25;
3456
+ function getViewportRect(element, strategy) {
3457
+ const win = getWindow(element);
3458
+ const html = getDocumentElement(element);
3459
+ const visualViewport = win.visualViewport;
3460
+ let width = html.clientWidth;
3461
+ let height = html.clientHeight;
3462
+ let x = 0;
3463
+ let y = 0;
3464
+ if (visualViewport) {
3465
+ width = visualViewport.width;
3466
+ height = visualViewport.height;
3467
+ const visualViewportBased = isWebKit();
3468
+ if (!visualViewportBased || visualViewportBased && strategy === 'fixed') {
3469
+ x = visualViewport.offsetLeft;
3470
+ y = visualViewport.offsetTop;
3471
+ }
3472
+ }
3473
+ const windowScrollbarX = getWindowScrollBarX(html);
3474
+ // <html> `overflow: hidden` + `scrollbar-gutter: stable` reduces the
3475
+ // visual width of the <html> but this is not considered in the size
3476
+ // of `html.clientWidth`.
3477
+ if (windowScrollbarX <= 0) {
3478
+ const doc = html.ownerDocument;
3479
+ const body = doc.body;
3480
+ const bodyStyles = getComputedStyle(body);
3481
+ const bodyMarginInline = doc.compatMode === 'CSS1Compat' ? parseFloat(bodyStyles.marginLeft) + parseFloat(bodyStyles.marginRight) || 0 : 0;
3482
+ const clippingStableScrollbarWidth = Math.abs(html.clientWidth - body.clientWidth - bodyMarginInline);
3483
+ if (clippingStableScrollbarWidth <= SCROLLBAR_MAX) {
3484
+ width -= clippingStableScrollbarWidth;
3485
+ }
3486
+ } else if (windowScrollbarX <= SCROLLBAR_MAX) {
3487
+ // If the <body> scrollbar is on the left, the width needs to be extended
3488
+ // by the scrollbar amount so there isn't extra space on the right.
3489
+ width += windowScrollbarX;
3490
+ }
3491
+ return {
3492
+ width,
3493
+ height,
3494
+ x,
3495
+ y
3496
+ };
3497
+ }
3498
+
3499
+ // Returns the inner client rect, subtracting scrollbars if present.
3500
+ function getInnerBoundingClientRect(element, strategy) {
3501
+ const clientRect = getBoundingClientRect(element, true, strategy === 'fixed');
3502
+ const top = clientRect.top + element.clientTop;
3503
+ const left = clientRect.left + element.clientLeft;
3504
+ const scale = isHTMLElement(element) ? getScale(element) : createCoords(1);
3505
+ const width = element.clientWidth * scale.x;
3506
+ const height = element.clientHeight * scale.y;
3507
+ const x = left * scale.x;
3508
+ const y = top * scale.y;
3509
+ return {
3510
+ width,
3511
+ height,
3512
+ x,
3513
+ y
3514
+ };
3515
+ }
3516
+ function getClientRectFromClippingAncestor(element, clippingAncestor, strategy) {
3517
+ let rect;
3518
+ if (clippingAncestor === 'viewport') {
3519
+ rect = getViewportRect(element, strategy);
3520
+ } else if (clippingAncestor === 'document') {
3521
+ rect = getDocumentRect(getDocumentElement(element));
3522
+ } else if (isElement(clippingAncestor)) {
3523
+ rect = getInnerBoundingClientRect(clippingAncestor, strategy);
3524
+ } else {
3525
+ const visualOffsets = getVisualOffsets(element);
3526
+ rect = {
3527
+ x: clippingAncestor.x - visualOffsets.x,
3528
+ y: clippingAncestor.y - visualOffsets.y,
3529
+ width: clippingAncestor.width,
3530
+ height: clippingAncestor.height
2102
3531
  };
2103
- const handleFocus = () => {
2104
- if (disabled)
2105
- return;
2106
- setIsVisible(true);
3532
+ }
3533
+ return rectToClientRect(rect);
3534
+ }
3535
+ function hasFixedPositionAncestor(element, stopNode) {
3536
+ const parentNode = getParentNode(element);
3537
+ if (parentNode === stopNode || !isElement(parentNode) || isLastTraversableNode(parentNode)) {
3538
+ return false;
3539
+ }
3540
+ return getComputedStyle$1(parentNode).position === 'fixed' || hasFixedPositionAncestor(parentNode, stopNode);
3541
+ }
3542
+
3543
+ // A "clipping ancestor" is an `overflow` element with the characteristic of
3544
+ // clipping (or hiding) child elements. This returns all clipping ancestors
3545
+ // of the given element up the tree.
3546
+ function getClippingElementAncestors(element, cache) {
3547
+ const cachedResult = cache.get(element);
3548
+ if (cachedResult) {
3549
+ return cachedResult;
3550
+ }
3551
+ let result = getOverflowAncestors(element, [], false).filter(el => isElement(el) && getNodeName(el) !== 'body');
3552
+ let currentContainingBlockComputedStyle = null;
3553
+ const elementIsFixed = getComputedStyle$1(element).position === 'fixed';
3554
+ let currentNode = elementIsFixed ? getParentNode(element) : element;
3555
+
3556
+ // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block
3557
+ while (isElement(currentNode) && !isLastTraversableNode(currentNode)) {
3558
+ const computedStyle = getComputedStyle$1(currentNode);
3559
+ const currentNodeIsContaining = isContainingBlock(currentNode);
3560
+ if (!currentNodeIsContaining && computedStyle.position === 'fixed') {
3561
+ currentContainingBlockComputedStyle = null;
3562
+ }
3563
+ const shouldDropCurrentNode = elementIsFixed ? !currentNodeIsContaining && !currentContainingBlockComputedStyle : !currentNodeIsContaining && computedStyle.position === 'static' && !!currentContainingBlockComputedStyle && (currentContainingBlockComputedStyle.position === 'absolute' || currentContainingBlockComputedStyle.position === 'fixed') || isOverflowElement(currentNode) && !currentNodeIsContaining && hasFixedPositionAncestor(element, currentNode);
3564
+ if (shouldDropCurrentNode) {
3565
+ // Drop non-containing blocks.
3566
+ result = result.filter(ancestor => ancestor !== currentNode);
3567
+ } else {
3568
+ // Record last containing block for next iteration.
3569
+ currentContainingBlockComputedStyle = computedStyle;
3570
+ }
3571
+ currentNode = getParentNode(currentNode);
3572
+ }
3573
+ cache.set(element, result);
3574
+ return result;
3575
+ }
3576
+
3577
+ // Gets the maximum area that the element is visible in due to any number of
3578
+ // clipping ancestors.
3579
+ function getClippingRect(_ref) {
3580
+ let {
3581
+ element,
3582
+ boundary,
3583
+ rootBoundary,
3584
+ strategy
3585
+ } = _ref;
3586
+ const elementClippingAncestors = boundary === 'clippingAncestors' ? isTopLayer(element) ? [] : getClippingElementAncestors(element, this._c) : [].concat(boundary);
3587
+ const clippingAncestors = [...elementClippingAncestors, rootBoundary];
3588
+ const firstRect = getClientRectFromClippingAncestor(element, clippingAncestors[0], strategy);
3589
+ let top = firstRect.top;
3590
+ let right = firstRect.right;
3591
+ let bottom = firstRect.bottom;
3592
+ let left = firstRect.left;
3593
+ for (let i = 1; i < clippingAncestors.length; i++) {
3594
+ const rect = getClientRectFromClippingAncestor(element, clippingAncestors[i], strategy);
3595
+ top = max(rect.top, top);
3596
+ right = min(rect.right, right);
3597
+ bottom = min(rect.bottom, bottom);
3598
+ left = max(rect.left, left);
3599
+ }
3600
+ return {
3601
+ width: right - left,
3602
+ height: bottom - top,
3603
+ x: left,
3604
+ y: top
3605
+ };
3606
+ }
3607
+
3608
+ function getDimensions(element) {
3609
+ const {
3610
+ width,
3611
+ height
3612
+ } = getCssDimensions(element);
3613
+ return {
3614
+ width,
3615
+ height
3616
+ };
3617
+ }
3618
+
3619
+ function getRectRelativeToOffsetParent(element, offsetParent, strategy) {
3620
+ const isOffsetParentAnElement = isHTMLElement(offsetParent);
3621
+ const documentElement = getDocumentElement(offsetParent);
3622
+ const isFixed = strategy === 'fixed';
3623
+ const rect = getBoundingClientRect(element, true, isFixed, offsetParent);
3624
+ let scroll = {
3625
+ scrollLeft: 0,
3626
+ scrollTop: 0
3627
+ };
3628
+ const offsets = createCoords(0);
3629
+
3630
+ // If the <body> scrollbar appears on the left (e.g. RTL systems). Use
3631
+ // Firefox with layout.scrollbar.side = 3 in about:config to test this.
3632
+ function setLeftRTLScrollbarOffset() {
3633
+ offsets.x = getWindowScrollBarX(documentElement);
3634
+ }
3635
+ if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {
3636
+ if (getNodeName(offsetParent) !== 'body' || isOverflowElement(documentElement)) {
3637
+ scroll = getNodeScroll(offsetParent);
3638
+ }
3639
+ if (isOffsetParentAnElement) {
3640
+ const offsetRect = getBoundingClientRect(offsetParent, true, isFixed, offsetParent);
3641
+ offsets.x = offsetRect.x + offsetParent.clientLeft;
3642
+ offsets.y = offsetRect.y + offsetParent.clientTop;
3643
+ } else if (documentElement) {
3644
+ setLeftRTLScrollbarOffset();
3645
+ }
3646
+ }
3647
+ if (isFixed && !isOffsetParentAnElement && documentElement) {
3648
+ setLeftRTLScrollbarOffset();
3649
+ }
3650
+ const htmlOffset = documentElement && !isOffsetParentAnElement && !isFixed ? getHTMLOffset(documentElement, scroll) : createCoords(0);
3651
+ const x = rect.left + scroll.scrollLeft - offsets.x - htmlOffset.x;
3652
+ const y = rect.top + scroll.scrollTop - offsets.y - htmlOffset.y;
3653
+ return {
3654
+ x,
3655
+ y,
3656
+ width: rect.width,
3657
+ height: rect.height
3658
+ };
3659
+ }
3660
+
3661
+ function isStaticPositioned(element) {
3662
+ return getComputedStyle$1(element).position === 'static';
3663
+ }
3664
+
3665
+ function getTrueOffsetParent(element, polyfill) {
3666
+ if (!isHTMLElement(element) || getComputedStyle$1(element).position === 'fixed') {
3667
+ return null;
3668
+ }
3669
+ if (polyfill) {
3670
+ return polyfill(element);
3671
+ }
3672
+ let rawOffsetParent = element.offsetParent;
3673
+
3674
+ // Firefox returns the <html> element as the offsetParent if it's non-static,
3675
+ // while Chrome and Safari return the <body> element. The <body> element must
3676
+ // be used to perform the correct calculations even if the <html> element is
3677
+ // non-static.
3678
+ if (getDocumentElement(element) === rawOffsetParent) {
3679
+ rawOffsetParent = rawOffsetParent.ownerDocument.body;
3680
+ }
3681
+ return rawOffsetParent;
3682
+ }
3683
+
3684
+ // Gets the closest ancestor positioned element. Handles some edge cases,
3685
+ // such as table ancestors and cross browser bugs.
3686
+ function getOffsetParent(element, polyfill) {
3687
+ const win = getWindow(element);
3688
+ if (isTopLayer(element)) {
3689
+ return win;
3690
+ }
3691
+ if (!isHTMLElement(element)) {
3692
+ let svgOffsetParent = getParentNode(element);
3693
+ while (svgOffsetParent && !isLastTraversableNode(svgOffsetParent)) {
3694
+ if (isElement(svgOffsetParent) && !isStaticPositioned(svgOffsetParent)) {
3695
+ return svgOffsetParent;
3696
+ }
3697
+ svgOffsetParent = getParentNode(svgOffsetParent);
3698
+ }
3699
+ return win;
3700
+ }
3701
+ let offsetParent = getTrueOffsetParent(element, polyfill);
3702
+ while (offsetParent && isTableElement(offsetParent) && isStaticPositioned(offsetParent)) {
3703
+ offsetParent = getTrueOffsetParent(offsetParent, polyfill);
3704
+ }
3705
+ if (offsetParent && isLastTraversableNode(offsetParent) && isStaticPositioned(offsetParent) && !isContainingBlock(offsetParent)) {
3706
+ return win;
3707
+ }
3708
+ return offsetParent || getContainingBlock(element) || win;
3709
+ }
3710
+
3711
+ const getElementRects = async function (data) {
3712
+ const getOffsetParentFn = this.getOffsetParent || getOffsetParent;
3713
+ const getDimensionsFn = this.getDimensions;
3714
+ const floatingDimensions = await getDimensionsFn(data.floating);
3715
+ return {
3716
+ reference: getRectRelativeToOffsetParent(data.reference, await getOffsetParentFn(data.floating), data.strategy),
3717
+ floating: {
3718
+ x: 0,
3719
+ y: 0,
3720
+ width: floatingDimensions.width,
3721
+ height: floatingDimensions.height
3722
+ }
3723
+ };
3724
+ };
3725
+
3726
+ function isRTL(element) {
3727
+ return getComputedStyle$1(element).direction === 'rtl';
3728
+ }
3729
+
3730
+ const platform = {
3731
+ convertOffsetParentRelativeRectToViewportRelativeRect,
3732
+ getDocumentElement,
3733
+ getClippingRect,
3734
+ getOffsetParent,
3735
+ getElementRects,
3736
+ getClientRects,
3737
+ getDimensions,
3738
+ getScale,
3739
+ isElement,
3740
+ isRTL
3741
+ };
3742
+
3743
+ function rectsAreEqual(a, b) {
3744
+ return a.x === b.x && a.y === b.y && a.width === b.width && a.height === b.height;
3745
+ }
3746
+
3747
+ // https://samthor.au/2021/observing-dom/
3748
+ function observeMove(element, onMove) {
3749
+ let io = null;
3750
+ let timeoutId;
3751
+ const root = getDocumentElement(element);
3752
+ function cleanup() {
3753
+ var _io;
3754
+ clearTimeout(timeoutId);
3755
+ (_io = io) == null || _io.disconnect();
3756
+ io = null;
3757
+ }
3758
+ function refresh(skip, threshold) {
3759
+ if (skip === void 0) {
3760
+ skip = false;
3761
+ }
3762
+ if (threshold === void 0) {
3763
+ threshold = 1;
3764
+ }
3765
+ cleanup();
3766
+ const elementRectForRootMargin = element.getBoundingClientRect();
3767
+ const {
3768
+ left,
3769
+ top,
3770
+ width,
3771
+ height
3772
+ } = elementRectForRootMargin;
3773
+ if (!skip) {
3774
+ onMove();
3775
+ }
3776
+ if (!width || !height) {
3777
+ return;
3778
+ }
3779
+ const insetTop = floor(top);
3780
+ const insetRight = floor(root.clientWidth - (left + width));
3781
+ const insetBottom = floor(root.clientHeight - (top + height));
3782
+ const insetLeft = floor(left);
3783
+ const rootMargin = -insetTop + "px " + -insetRight + "px " + -insetBottom + "px " + -insetLeft + "px";
3784
+ const options = {
3785
+ rootMargin,
3786
+ threshold: max(0, min(1, threshold)) || 1
2107
3787
  };
2108
- const handleBlur = () => {
2109
- setIsVisible(false);
3788
+ let isFirstUpdate = true;
3789
+ function handleObserve(entries) {
3790
+ const ratio = entries[0].intersectionRatio;
3791
+ if (ratio !== threshold) {
3792
+ if (!isFirstUpdate) {
3793
+ return refresh();
3794
+ }
3795
+ if (!ratio) {
3796
+ // If the reference is clipped, the ratio is 0. Throttle the refresh
3797
+ // to prevent an infinite loop of updates.
3798
+ timeoutId = setTimeout(() => {
3799
+ refresh(false, 1e-7);
3800
+ }, 1000);
3801
+ } else {
3802
+ refresh(false, ratio);
3803
+ }
3804
+ }
3805
+ if (ratio === 1 && !rectsAreEqual(elementRectForRootMargin, element.getBoundingClientRect())) {
3806
+ // It's possible that even though the ratio is reported as 1, the
3807
+ // element is not actually fully within the IntersectionObserver's root
3808
+ // area anymore. This can happen under performance constraints. This may
3809
+ // be a bug in the browser's IntersectionObserver implementation. To
3810
+ // work around this, we compare the element's bounding rect now with
3811
+ // what it was at the time we created the IntersectionObserver. If they
3812
+ // are not equal then the element moved, so we refresh.
3813
+ refresh();
3814
+ }
3815
+ isFirstUpdate = false;
3816
+ }
3817
+
3818
+ // Older browsers don't support a `document` as the root and will throw an
3819
+ // error.
3820
+ try {
3821
+ io = new IntersectionObserver(handleObserve, {
3822
+ ...options,
3823
+ // Handle <iframe>s
3824
+ root: root.ownerDocument
3825
+ });
3826
+ } catch (_e) {
3827
+ io = new IntersectionObserver(handleObserve, options);
3828
+ }
3829
+ io.observe(element);
3830
+ }
3831
+ refresh(true);
3832
+ return cleanup;
3833
+ }
3834
+
3835
+ /**
3836
+ * Automatically updates the position of the floating element when necessary.
3837
+ * Should only be called when the floating element is mounted on the DOM or
3838
+ * visible on the screen.
3839
+ * @returns cleanup function that should be invoked when the floating element is
3840
+ * removed from the DOM or hidden from the screen.
3841
+ * @see https://floating-ui.com/docs/autoUpdate
3842
+ */
3843
+ function autoUpdate(reference, floating, update, options) {
3844
+ if (options === void 0) {
3845
+ options = {};
3846
+ }
3847
+ const {
3848
+ ancestorScroll = true,
3849
+ ancestorResize = true,
3850
+ elementResize = typeof ResizeObserver === 'function',
3851
+ layoutShift = typeof IntersectionObserver === 'function',
3852
+ animationFrame = false
3853
+ } = options;
3854
+ const referenceEl = unwrapElement(reference);
3855
+ const ancestors = ancestorScroll || ancestorResize ? [...(referenceEl ? getOverflowAncestors(referenceEl) : []), ...(floating ? getOverflowAncestors(floating) : [])] : [];
3856
+ ancestors.forEach(ancestor => {
3857
+ ancestorScroll && ancestor.addEventListener('scroll', update, {
3858
+ passive: true
3859
+ });
3860
+ ancestorResize && ancestor.addEventListener('resize', update);
3861
+ });
3862
+ const cleanupIo = referenceEl && layoutShift ? observeMove(referenceEl, update) : null;
3863
+ let reobserveFrame = -1;
3864
+ let resizeObserver = null;
3865
+ if (elementResize) {
3866
+ resizeObserver = new ResizeObserver(_ref => {
3867
+ let [firstEntry] = _ref;
3868
+ if (firstEntry && firstEntry.target === referenceEl && resizeObserver && floating) {
3869
+ // Prevent update loops when using the `size` middleware.
3870
+ // https://github.com/floating-ui/floating-ui/issues/1740
3871
+ resizeObserver.unobserve(floating);
3872
+ cancelAnimationFrame(reobserveFrame);
3873
+ reobserveFrame = requestAnimationFrame(() => {
3874
+ var _resizeObserver;
3875
+ (_resizeObserver = resizeObserver) == null || _resizeObserver.observe(floating);
3876
+ });
3877
+ }
3878
+ update();
3879
+ });
3880
+ if (referenceEl && !animationFrame) {
3881
+ resizeObserver.observe(referenceEl);
3882
+ }
3883
+ if (floating) {
3884
+ resizeObserver.observe(floating);
3885
+ }
3886
+ }
3887
+ let frameId;
3888
+ let prevRefRect = animationFrame ? getBoundingClientRect(reference) : null;
3889
+ if (animationFrame) {
3890
+ frameLoop();
3891
+ }
3892
+ function frameLoop() {
3893
+ const nextRefRect = getBoundingClientRect(reference);
3894
+ if (prevRefRect && !rectsAreEqual(prevRefRect, nextRefRect)) {
3895
+ update();
3896
+ }
3897
+ prevRefRect = nextRefRect;
3898
+ frameId = requestAnimationFrame(frameLoop);
3899
+ }
3900
+ update();
3901
+ return () => {
3902
+ var _resizeObserver2;
3903
+ ancestors.forEach(ancestor => {
3904
+ ancestorScroll && ancestor.removeEventListener('scroll', update);
3905
+ ancestorResize && ancestor.removeEventListener('resize', update);
3906
+ });
3907
+ cleanupIo == null || cleanupIo();
3908
+ (_resizeObserver2 = resizeObserver) == null || _resizeObserver2.disconnect();
3909
+ resizeObserver = null;
3910
+ if (animationFrame) {
3911
+ cancelAnimationFrame(frameId);
3912
+ }
3913
+ };
3914
+ }
3915
+
3916
+ /**
3917
+ * Modifies the placement by translating the floating element along the
3918
+ * specified axes.
3919
+ * A number (shorthand for `mainAxis` or distance), or an axes configuration
3920
+ * object may be passed.
3921
+ * @see https://floating-ui.com/docs/offset
3922
+ */
3923
+ const offset$1 = offset$2;
3924
+
3925
+ /**
3926
+ * Optimizes the visibility of the floating element by shifting it in order to
3927
+ * keep it in view when it will overflow the clipping boundary.
3928
+ * @see https://floating-ui.com/docs/shift
3929
+ */
3930
+ const shift$1 = shift$2;
3931
+
3932
+ /**
3933
+ * Optimizes the visibility of the floating element by flipping the `placement`
3934
+ * in order to keep it in view when the preferred placement(s) will overflow the
3935
+ * clipping boundary. Alternative to `autoPlacement`.
3936
+ * @see https://floating-ui.com/docs/flip
3937
+ */
3938
+ const flip$1 = flip$2;
3939
+
3940
+ /**
3941
+ * Provides data that allows you to change the size of the floating element —
3942
+ * for instance, prevent it from overflowing the clipping boundary or match the
3943
+ * width of the reference element.
3944
+ * @see https://floating-ui.com/docs/size
3945
+ */
3946
+ const size$1 = size$2;
3947
+
3948
+ /**
3949
+ * Provides data to hide the floating element in applicable situations, such as
3950
+ * when it is not in the same clipping context as the reference element.
3951
+ * @see https://floating-ui.com/docs/hide
3952
+ */
3953
+ const hide$1 = hide$2;
3954
+
3955
+ /**
3956
+ * Provides data to position an inner element of the floating element so that it
3957
+ * appears centered to the reference element.
3958
+ * @see https://floating-ui.com/docs/arrow
3959
+ */
3960
+ const arrow$2 = arrow$3;
3961
+
3962
+ /**
3963
+ * Built-in `limiter` that will stop `shift()` at a certain point.
3964
+ */
3965
+ const limitShift$1 = limitShift$2;
3966
+
3967
+ /**
3968
+ * Computes the `x` and `y` coordinates that will place the floating element
3969
+ * next to a given reference element.
3970
+ */
3971
+ const computePosition = (reference, floating, options) => {
3972
+ // This caches the expensive `getClippingElementAncestors` function so that
3973
+ // multiple lifecycle resets re-use the same result. It only lives for a
3974
+ // single call. If other functions become expensive, we can add them as well.
3975
+ const cache = new Map();
3976
+ const mergedOptions = {
3977
+ platform,
3978
+ ...options
3979
+ };
3980
+ const platformWithCache = {
3981
+ ...mergedOptions.platform,
3982
+ _c: cache
3983
+ };
3984
+ return computePosition$1(reference, floating, {
3985
+ ...mergedOptions,
3986
+ platform: platformWithCache
3987
+ });
3988
+ };
3989
+
3990
+ var isClient = typeof document !== 'undefined';
3991
+
3992
+ var noop = function noop() {};
3993
+ var index = isClient ? useLayoutEffect : noop;
3994
+
3995
+ // Fork of `fast-deep-equal` that only does the comparisons we need and compares
3996
+ // functions
3997
+ function deepEqual(a, b) {
3998
+ if (a === b) {
3999
+ return true;
4000
+ }
4001
+ if (typeof a !== typeof b) {
4002
+ return false;
4003
+ }
4004
+ if (typeof a === 'function' && a.toString() === b.toString()) {
4005
+ return true;
4006
+ }
4007
+ let length;
4008
+ let i;
4009
+ let keys;
4010
+ if (a && b && typeof a === 'object') {
4011
+ if (Array.isArray(a)) {
4012
+ length = a.length;
4013
+ if (length !== b.length) return false;
4014
+ for (i = length; i-- !== 0;) {
4015
+ if (!deepEqual(a[i], b[i])) {
4016
+ return false;
4017
+ }
4018
+ }
4019
+ return true;
4020
+ }
4021
+ keys = Object.keys(a);
4022
+ length = keys.length;
4023
+ if (length !== Object.keys(b).length) {
4024
+ return false;
4025
+ }
4026
+ for (i = length; i-- !== 0;) {
4027
+ if (!{}.hasOwnProperty.call(b, keys[i])) {
4028
+ return false;
4029
+ }
4030
+ }
4031
+ for (i = length; i-- !== 0;) {
4032
+ const key = keys[i];
4033
+ if (key === '_owner' && a.$$typeof) {
4034
+ continue;
4035
+ }
4036
+ if (!deepEqual(a[key], b[key])) {
4037
+ return false;
4038
+ }
4039
+ }
4040
+ return true;
4041
+ }
4042
+ return a !== a && b !== b;
4043
+ }
4044
+
4045
+ function getDPR(element) {
4046
+ if (typeof window === 'undefined') {
4047
+ return 1;
4048
+ }
4049
+ const win = element.ownerDocument.defaultView || window;
4050
+ return win.devicePixelRatio || 1;
4051
+ }
4052
+
4053
+ function roundByDPR(element, value) {
4054
+ const dpr = getDPR(element);
4055
+ return Math.round(value * dpr) / dpr;
4056
+ }
4057
+
4058
+ function useLatestRef(value) {
4059
+ const ref = React.useRef(value);
4060
+ index(() => {
4061
+ ref.current = value;
4062
+ });
4063
+ return ref;
4064
+ }
4065
+
4066
+ /**
4067
+ * Provides data to position a floating element.
4068
+ * @see https://floating-ui.com/docs/useFloating
4069
+ */
4070
+ function useFloating(options) {
4071
+ if (options === void 0) {
4072
+ options = {};
4073
+ }
4074
+ const {
4075
+ placement = 'bottom',
4076
+ strategy = 'absolute',
4077
+ middleware = [],
4078
+ platform,
4079
+ elements: {
4080
+ reference: externalReference,
4081
+ floating: externalFloating
4082
+ } = {},
4083
+ transform = true,
4084
+ whileElementsMounted,
4085
+ open
4086
+ } = options;
4087
+ const [data, setData] = React.useState({
4088
+ x: 0,
4089
+ y: 0,
4090
+ strategy,
4091
+ placement,
4092
+ middlewareData: {},
4093
+ isPositioned: false
4094
+ });
4095
+ const [latestMiddleware, setLatestMiddleware] = React.useState(middleware);
4096
+ if (!deepEqual(latestMiddleware, middleware)) {
4097
+ setLatestMiddleware(middleware);
4098
+ }
4099
+ const [_reference, _setReference] = React.useState(null);
4100
+ const [_floating, _setFloating] = React.useState(null);
4101
+ const setReference = React.useCallback(node => {
4102
+ if (node !== referenceRef.current) {
4103
+ referenceRef.current = node;
4104
+ _setReference(node);
4105
+ }
4106
+ }, []);
4107
+ const setFloating = React.useCallback(node => {
4108
+ if (node !== floatingRef.current) {
4109
+ floatingRef.current = node;
4110
+ _setFloating(node);
4111
+ }
4112
+ }, []);
4113
+ const referenceEl = externalReference || _reference;
4114
+ const floatingEl = externalFloating || _floating;
4115
+ const referenceRef = React.useRef(null);
4116
+ const floatingRef = React.useRef(null);
4117
+ const dataRef = React.useRef(data);
4118
+ const hasWhileElementsMounted = whileElementsMounted != null;
4119
+ const whileElementsMountedRef = useLatestRef(whileElementsMounted);
4120
+ const platformRef = useLatestRef(platform);
4121
+ const openRef = useLatestRef(open);
4122
+ const update = React.useCallback(() => {
4123
+ if (!referenceRef.current || !floatingRef.current) {
4124
+ return;
4125
+ }
4126
+ const config = {
4127
+ placement,
4128
+ strategy,
4129
+ middleware: latestMiddleware
4130
+ };
4131
+ if (platformRef.current) {
4132
+ config.platform = platformRef.current;
4133
+ }
4134
+ computePosition(referenceRef.current, floatingRef.current, config).then(data => {
4135
+ const fullData = {
4136
+ ...data,
4137
+ // The floating element's position may be recomputed while it's closed
4138
+ // but still mounted (such as when transitioning out). To ensure
4139
+ // `isPositioned` will be `false` initially on the next open, avoid
4140
+ // setting it to `true` when `open === false` (must be specified).
4141
+ isPositioned: openRef.current !== false
4142
+ };
4143
+ if (isMountedRef.current && !deepEqual(dataRef.current, fullData)) {
4144
+ dataRef.current = fullData;
4145
+ ReactDOM.flushSync(() => {
4146
+ setData(fullData);
4147
+ });
4148
+ }
4149
+ });
4150
+ }, [latestMiddleware, placement, strategy, platformRef, openRef]);
4151
+ index(() => {
4152
+ if (open === false && dataRef.current.isPositioned) {
4153
+ dataRef.current.isPositioned = false;
4154
+ setData(data => ({
4155
+ ...data,
4156
+ isPositioned: false
4157
+ }));
4158
+ }
4159
+ }, [open]);
4160
+ const isMountedRef = React.useRef(false);
4161
+ index(() => {
4162
+ isMountedRef.current = true;
4163
+ return () => {
4164
+ isMountedRef.current = false;
4165
+ };
4166
+ }, []);
4167
+ index(() => {
4168
+ if (referenceEl) referenceRef.current = referenceEl;
4169
+ if (floatingEl) floatingRef.current = floatingEl;
4170
+ if (referenceEl && floatingEl) {
4171
+ if (whileElementsMountedRef.current) {
4172
+ return whileElementsMountedRef.current(referenceEl, floatingEl, update);
4173
+ }
4174
+ update();
4175
+ }
4176
+ }, [referenceEl, floatingEl, update, whileElementsMountedRef, hasWhileElementsMounted]);
4177
+ const refs = React.useMemo(() => ({
4178
+ reference: referenceRef,
4179
+ floating: floatingRef,
4180
+ setReference,
4181
+ setFloating
4182
+ }), [setReference, setFloating]);
4183
+ const elements = React.useMemo(() => ({
4184
+ reference: referenceEl,
4185
+ floating: floatingEl
4186
+ }), [referenceEl, floatingEl]);
4187
+ const floatingStyles = React.useMemo(() => {
4188
+ const initialStyles = {
4189
+ position: strategy,
4190
+ left: 0,
4191
+ top: 0
4192
+ };
4193
+ if (!elements.floating) {
4194
+ return initialStyles;
4195
+ }
4196
+ const x = roundByDPR(elements.floating, data.x);
4197
+ const y = roundByDPR(elements.floating, data.y);
4198
+ if (transform) {
4199
+ return {
4200
+ ...initialStyles,
4201
+ transform: "translate(" + x + "px, " + y + "px)",
4202
+ ...(getDPR(elements.floating) >= 1.5 && {
4203
+ willChange: 'transform'
4204
+ })
4205
+ };
4206
+ }
4207
+ return {
4208
+ position: strategy,
4209
+ left: x,
4210
+ top: y
4211
+ };
4212
+ }, [strategy, transform, elements.floating, data.x, data.y]);
4213
+ return React.useMemo(() => ({
4214
+ ...data,
4215
+ update,
4216
+ refs,
4217
+ elements,
4218
+ floatingStyles
4219
+ }), [data, update, refs, elements, floatingStyles]);
4220
+ }
4221
+
4222
+ /**
4223
+ * Provides data to position an inner element of the floating element so that it
4224
+ * appears centered to the reference element.
4225
+ * This wraps the core `arrow` middleware to allow React refs as the element.
4226
+ * @see https://floating-ui.com/docs/arrow
4227
+ */
4228
+ const arrow$1 = options => {
4229
+ function isRef(value) {
4230
+ return {}.hasOwnProperty.call(value, 'current');
4231
+ }
4232
+ return {
4233
+ name: 'arrow',
4234
+ options,
4235
+ fn(state) {
4236
+ const {
4237
+ element,
4238
+ padding
4239
+ } = typeof options === 'function' ? options(state) : options;
4240
+ if (element && isRef(element)) {
4241
+ if (element.current != null) {
4242
+ return arrow$2({
4243
+ element: element.current,
4244
+ padding
4245
+ }).fn(state);
4246
+ }
4247
+ return {};
4248
+ }
4249
+ if (element) {
4250
+ return arrow$2({
4251
+ element,
4252
+ padding
4253
+ }).fn(state);
4254
+ }
4255
+ return {};
4256
+ }
4257
+ };
4258
+ };
4259
+
4260
+ /**
4261
+ * Modifies the placement by translating the floating element along the
4262
+ * specified axes.
4263
+ * A number (shorthand for `mainAxis` or distance), or an axes configuration
4264
+ * object may be passed.
4265
+ * @see https://floating-ui.com/docs/offset
4266
+ */
4267
+ const offset = (options, deps) => {
4268
+ const result = offset$1(options);
4269
+ return {
4270
+ name: result.name,
4271
+ fn: result.fn,
4272
+ options: [options, deps]
4273
+ };
4274
+ };
4275
+
4276
+ /**
4277
+ * Optimizes the visibility of the floating element by shifting it in order to
4278
+ * keep it in view when it will overflow the clipping boundary.
4279
+ * @see https://floating-ui.com/docs/shift
4280
+ */
4281
+ const shift = (options, deps) => {
4282
+ const result = shift$1(options);
4283
+ return {
4284
+ name: result.name,
4285
+ fn: result.fn,
4286
+ options: [options, deps]
4287
+ };
4288
+ };
4289
+
4290
+ /**
4291
+ * Built-in `limiter` that will stop `shift()` at a certain point.
4292
+ */
4293
+ const limitShift = (options, deps) => {
4294
+ const result = limitShift$1(options);
4295
+ return {
4296
+ fn: result.fn,
4297
+ options: [options, deps]
4298
+ };
4299
+ };
4300
+
4301
+ /**
4302
+ * Optimizes the visibility of the floating element by flipping the `placement`
4303
+ * in order to keep it in view when the preferred placement(s) will overflow the
4304
+ * clipping boundary. Alternative to `autoPlacement`.
4305
+ * @see https://floating-ui.com/docs/flip
4306
+ */
4307
+ const flip = (options, deps) => {
4308
+ const result = flip$1(options);
4309
+ return {
4310
+ name: result.name,
4311
+ fn: result.fn,
4312
+ options: [options, deps]
4313
+ };
4314
+ };
4315
+
4316
+ /**
4317
+ * Provides data that allows you to change the size of the floating element —
4318
+ * for instance, prevent it from overflowing the clipping boundary or match the
4319
+ * width of the reference element.
4320
+ * @see https://floating-ui.com/docs/size
4321
+ */
4322
+ const size = (options, deps) => {
4323
+ const result = size$1(options);
4324
+ return {
4325
+ name: result.name,
4326
+ fn: result.fn,
4327
+ options: [options, deps]
4328
+ };
4329
+ };
4330
+
4331
+ /**
4332
+ * Provides data to hide the floating element in applicable situations, such as
4333
+ * when it is not in the same clipping context as the reference element.
4334
+ * @see https://floating-ui.com/docs/hide
4335
+ */
4336
+ const hide = (options, deps) => {
4337
+ const result = hide$1(options);
4338
+ return {
4339
+ name: result.name,
4340
+ fn: result.fn,
4341
+ options: [options, deps]
4342
+ };
4343
+ };
4344
+
4345
+ /**
4346
+ * Provides data to position an inner element of the floating element so that it
4347
+ * appears centered to the reference element.
4348
+ * This wraps the core `arrow` middleware to allow React refs as the element.
4349
+ * @see https://floating-ui.com/docs/arrow
4350
+ */
4351
+ const arrow = (options, deps) => {
4352
+ const result = arrow$1(options);
4353
+ return {
4354
+ name: result.name,
4355
+ fn: result.fn,
4356
+ options: [options, deps]
4357
+ };
4358
+ };
4359
+
4360
+ // src/primitive.tsx
4361
+ var NODES = [
4362
+ "a",
4363
+ "button",
4364
+ "div",
4365
+ "form",
4366
+ "h2",
4367
+ "h3",
4368
+ "img",
4369
+ "input",
4370
+ "label",
4371
+ "li",
4372
+ "nav",
4373
+ "ol",
4374
+ "p",
4375
+ "select",
4376
+ "span",
4377
+ "svg",
4378
+ "ul"
4379
+ ];
4380
+ var Primitive = NODES.reduce((primitive, node) => {
4381
+ const Slot = createSlot(`Primitive.${node}`);
4382
+ const Node = React.forwardRef((props, forwardedRef) => {
4383
+ const { asChild, ...primitiveProps } = props;
4384
+ const Comp = asChild ? Slot : node;
4385
+ if (typeof window !== "undefined") {
4386
+ window[Symbol.for("radix-ui")] = true;
4387
+ }
4388
+ return /* @__PURE__ */ jsx(Comp, { ...primitiveProps, ref: forwardedRef });
4389
+ });
4390
+ Node.displayName = `Primitive.${node}`;
4391
+ return { ...primitive, [node]: Node };
4392
+ }, {});
4393
+ function dispatchDiscreteCustomEvent(target, event) {
4394
+ if (target) ReactDOM.flushSync(() => target.dispatchEvent(event));
4395
+ }
4396
+
4397
+ // src/arrow.tsx
4398
+ var NAME = "Arrow";
4399
+ var Arrow$1 = React.forwardRef((props, forwardedRef) => {
4400
+ const { children, width = 10, height = 5, ...arrowProps } = props;
4401
+ return /* @__PURE__ */ jsx(
4402
+ Primitive.svg,
4403
+ {
4404
+ ...arrowProps,
4405
+ ref: forwardedRef,
4406
+ width,
4407
+ height,
4408
+ viewBox: "0 0 30 10",
4409
+ preserveAspectRatio: "none",
4410
+ children: props.asChild ? children : /* @__PURE__ */ jsx("polygon", { points: "0,0 30,0 15,10" })
4411
+ }
4412
+ );
4413
+ });
4414
+ Arrow$1.displayName = NAME;
4415
+ var Root = Arrow$1;
4416
+
4417
+ // packages/react/use-callback-ref/src/use-callback-ref.tsx
4418
+ function useCallbackRef(callback) {
4419
+ const callbackRef = React.useRef(callback);
4420
+ React.useEffect(() => {
4421
+ callbackRef.current = callback;
4422
+ });
4423
+ return React.useMemo(() => (...args) => callbackRef.current?.(...args), []);
4424
+ }
4425
+
4426
+ // packages/react/use-size/src/use-size.tsx
4427
+ function useSize(element) {
4428
+ const [size, setSize] = React.useState(void 0);
4429
+ useLayoutEffect2(() => {
4430
+ if (element) {
4431
+ setSize({ width: element.offsetWidth, height: element.offsetHeight });
4432
+ const resizeObserver = new ResizeObserver((entries) => {
4433
+ if (!Array.isArray(entries)) {
4434
+ return;
4435
+ }
4436
+ if (!entries.length) {
4437
+ return;
4438
+ }
4439
+ const entry = entries[0];
4440
+ let width;
4441
+ let height;
4442
+ if ("borderBoxSize" in entry) {
4443
+ const borderSizeEntry = entry["borderBoxSize"];
4444
+ const borderSize = Array.isArray(borderSizeEntry) ? borderSizeEntry[0] : borderSizeEntry;
4445
+ width = borderSize["inlineSize"];
4446
+ height = borderSize["blockSize"];
4447
+ } else {
4448
+ width = element.offsetWidth;
4449
+ height = element.offsetHeight;
4450
+ }
4451
+ setSize({ width, height });
4452
+ });
4453
+ resizeObserver.observe(element, { box: "border-box" });
4454
+ return () => resizeObserver.unobserve(element);
4455
+ } else {
4456
+ setSize(void 0);
4457
+ }
4458
+ }, [element]);
4459
+ return size;
4460
+ }
4461
+
4462
+ var POPPER_NAME = "Popper";
4463
+ var [createPopperContext, createPopperScope] = createContextScope(POPPER_NAME);
4464
+ var [PopperProvider, usePopperContext] = createPopperContext(POPPER_NAME);
4465
+ var Popper = (props) => {
4466
+ const { __scopePopper, children } = props;
4467
+ const [anchor, setAnchor] = React.useState(null);
4468
+ return /* @__PURE__ */ jsx(PopperProvider, { scope: __scopePopper, anchor, onAnchorChange: setAnchor, children });
4469
+ };
4470
+ Popper.displayName = POPPER_NAME;
4471
+ var ANCHOR_NAME = "PopperAnchor";
4472
+ var PopperAnchor = React.forwardRef(
4473
+ (props, forwardedRef) => {
4474
+ const { __scopePopper, virtualRef, ...anchorProps } = props;
4475
+ const context = usePopperContext(ANCHOR_NAME, __scopePopper);
4476
+ const ref = React.useRef(null);
4477
+ const composedRefs = useComposedRefs(forwardedRef, ref);
4478
+ const anchorRef = React.useRef(null);
4479
+ React.useEffect(() => {
4480
+ const previousAnchor = anchorRef.current;
4481
+ anchorRef.current = virtualRef?.current || ref.current;
4482
+ if (previousAnchor !== anchorRef.current) {
4483
+ context.onAnchorChange(anchorRef.current);
4484
+ }
4485
+ });
4486
+ return virtualRef ? null : /* @__PURE__ */ jsx(Primitive.div, { ...anchorProps, ref: composedRefs });
4487
+ }
4488
+ );
4489
+ PopperAnchor.displayName = ANCHOR_NAME;
4490
+ var CONTENT_NAME$1 = "PopperContent";
4491
+ var [PopperContentProvider, useContentContext] = createPopperContext(CONTENT_NAME$1);
4492
+ var PopperContent = React.forwardRef(
4493
+ (props, forwardedRef) => {
4494
+ const {
4495
+ __scopePopper,
4496
+ side = "bottom",
4497
+ sideOffset = 0,
4498
+ align = "center",
4499
+ alignOffset = 0,
4500
+ arrowPadding = 0,
4501
+ avoidCollisions = true,
4502
+ collisionBoundary = [],
4503
+ collisionPadding: collisionPaddingProp = 0,
4504
+ sticky = "partial",
4505
+ hideWhenDetached = false,
4506
+ updatePositionStrategy = "optimized",
4507
+ onPlaced,
4508
+ ...contentProps
4509
+ } = props;
4510
+ const context = usePopperContext(CONTENT_NAME$1, __scopePopper);
4511
+ const [content, setContent] = React.useState(null);
4512
+ const composedRefs = useComposedRefs(forwardedRef, (node) => setContent(node));
4513
+ const [arrow$1, setArrow] = React.useState(null);
4514
+ const arrowSize = useSize(arrow$1);
4515
+ const arrowWidth = arrowSize?.width ?? 0;
4516
+ const arrowHeight = arrowSize?.height ?? 0;
4517
+ const desiredPlacement = side + (align !== "center" ? "-" + align : "");
4518
+ const collisionPadding = typeof collisionPaddingProp === "number" ? collisionPaddingProp : { top: 0, right: 0, bottom: 0, left: 0, ...collisionPaddingProp };
4519
+ const boundary = Array.isArray(collisionBoundary) ? collisionBoundary : [collisionBoundary];
4520
+ const hasExplicitBoundaries = boundary.length > 0;
4521
+ const detectOverflowOptions = {
4522
+ padding: collisionPadding,
4523
+ boundary: boundary.filter(isNotNull),
4524
+ // with `strategy: 'fixed'`, this is the only way to get it to respect boundaries
4525
+ altBoundary: hasExplicitBoundaries
2110
4526
  };
4527
+ const { refs, floatingStyles, placement, isPositioned, middlewareData } = useFloating({
4528
+ // default to `fixed` strategy so users don't have to pick and we also avoid focus scroll issues
4529
+ strategy: "fixed",
4530
+ placement: desiredPlacement,
4531
+ whileElementsMounted: (...args) => {
4532
+ const cleanup = autoUpdate(...args, {
4533
+ animationFrame: updatePositionStrategy === "always"
4534
+ });
4535
+ return cleanup;
4536
+ },
4537
+ elements: {
4538
+ reference: context.anchor
4539
+ },
4540
+ middleware: [
4541
+ offset({ mainAxis: sideOffset + arrowHeight, alignmentAxis: alignOffset }),
4542
+ avoidCollisions && shift({
4543
+ mainAxis: true,
4544
+ crossAxis: false,
4545
+ limiter: sticky === "partial" ? limitShift() : void 0,
4546
+ ...detectOverflowOptions
4547
+ }),
4548
+ avoidCollisions && flip({ ...detectOverflowOptions }),
4549
+ size({
4550
+ ...detectOverflowOptions,
4551
+ apply: ({ elements, rects, availableWidth, availableHeight }) => {
4552
+ const { width: anchorWidth, height: anchorHeight } = rects.reference;
4553
+ const contentStyle = elements.floating.style;
4554
+ contentStyle.setProperty("--radix-popper-available-width", `${availableWidth}px`);
4555
+ contentStyle.setProperty("--radix-popper-available-height", `${availableHeight}px`);
4556
+ contentStyle.setProperty("--radix-popper-anchor-width", `${anchorWidth}px`);
4557
+ contentStyle.setProperty("--radix-popper-anchor-height", `${anchorHeight}px`);
4558
+ }
4559
+ }),
4560
+ arrow$1 && arrow({ element: arrow$1, padding: arrowPadding }),
4561
+ transformOrigin({ arrowWidth, arrowHeight }),
4562
+ hideWhenDetached && hide({ strategy: "referenceHidden", ...detectOverflowOptions })
4563
+ ]
4564
+ });
4565
+ const [placedSide, placedAlign] = getSideAndAlignFromPlacement(placement);
4566
+ const handlePlaced = useCallbackRef(onPlaced);
4567
+ useLayoutEffect2(() => {
4568
+ if (isPositioned) {
4569
+ handlePlaced?.();
4570
+ }
4571
+ }, [isPositioned, handlePlaced]);
4572
+ const arrowX = middlewareData.arrow?.x;
4573
+ const arrowY = middlewareData.arrow?.y;
4574
+ const cannotCenterArrow = middlewareData.arrow?.centerOffset !== 0;
4575
+ const [contentZIndex, setContentZIndex] = React.useState();
4576
+ useLayoutEffect2(() => {
4577
+ if (content) setContentZIndex(window.getComputedStyle(content).zIndex);
4578
+ }, [content]);
4579
+ return /* @__PURE__ */ jsx(
4580
+ "div",
4581
+ {
4582
+ ref: refs.setFloating,
4583
+ "data-radix-popper-content-wrapper": "",
4584
+ style: {
4585
+ ...floatingStyles,
4586
+ transform: isPositioned ? floatingStyles.transform : "translate(0, -200%)",
4587
+ // keep off the page when measuring
4588
+ minWidth: "max-content",
4589
+ zIndex: contentZIndex,
4590
+ ["--radix-popper-transform-origin"]: [
4591
+ middlewareData.transformOrigin?.x,
4592
+ middlewareData.transformOrigin?.y
4593
+ ].join(" "),
4594
+ // hide the content if using the hide middleware and should be hidden
4595
+ // set visibility to hidden and disable pointer events so the UI behaves
4596
+ // as if the PopperContent isn't there at all
4597
+ ...middlewareData.hide?.referenceHidden && {
4598
+ visibility: "hidden",
4599
+ pointerEvents: "none"
4600
+ }
4601
+ },
4602
+ dir: props.dir,
4603
+ children: /* @__PURE__ */ jsx(
4604
+ PopperContentProvider,
4605
+ {
4606
+ scope: __scopePopper,
4607
+ placedSide,
4608
+ onArrowChange: setArrow,
4609
+ arrowX,
4610
+ arrowY,
4611
+ shouldHideArrow: cannotCenterArrow,
4612
+ children: /* @__PURE__ */ jsx(
4613
+ Primitive.div,
4614
+ {
4615
+ "data-side": placedSide,
4616
+ "data-align": placedAlign,
4617
+ ...contentProps,
4618
+ ref: composedRefs,
4619
+ style: {
4620
+ ...contentProps.style,
4621
+ // if the PopperContent hasn't been placed yet (not all measurements done)
4622
+ // we prevent animations so that users's animation don't kick in too early referring wrong sides
4623
+ animation: !isPositioned ? "none" : void 0
4624
+ }
4625
+ }
4626
+ )
4627
+ }
4628
+ )
4629
+ }
4630
+ );
4631
+ }
4632
+ );
4633
+ PopperContent.displayName = CONTENT_NAME$1;
4634
+ var ARROW_NAME$1 = "PopperArrow";
4635
+ var OPPOSITE_SIDE = {
4636
+ top: "bottom",
4637
+ right: "left",
4638
+ bottom: "top",
4639
+ left: "right"
4640
+ };
4641
+ var PopperArrow = React.forwardRef(function PopperArrow2(props, forwardedRef) {
4642
+ const { __scopePopper, ...arrowProps } = props;
4643
+ const contentContext = useContentContext(ARROW_NAME$1, __scopePopper);
4644
+ const baseSide = OPPOSITE_SIDE[contentContext.placedSide];
4645
+ return (
4646
+ // we have to use an extra wrapper because `ResizeObserver` (used by `useSize`)
4647
+ // doesn't report size as we'd expect on SVG elements.
4648
+ // it reports their bounding box which is effectively the largest path inside the SVG.
4649
+ /* @__PURE__ */ jsx(
4650
+ "span",
4651
+ {
4652
+ ref: contentContext.onArrowChange,
4653
+ style: {
4654
+ position: "absolute",
4655
+ left: contentContext.arrowX,
4656
+ top: contentContext.arrowY,
4657
+ [baseSide]: 0,
4658
+ transformOrigin: {
4659
+ top: "",
4660
+ right: "0 0",
4661
+ bottom: "center 0",
4662
+ left: "100% 0"
4663
+ }[contentContext.placedSide],
4664
+ transform: {
4665
+ top: "translateY(100%)",
4666
+ right: "translateY(50%) rotate(90deg) translateX(-50%)",
4667
+ bottom: `rotate(180deg)`,
4668
+ left: "translateY(50%) rotate(-90deg) translateX(50%)"
4669
+ }[contentContext.placedSide],
4670
+ visibility: contentContext.shouldHideArrow ? "hidden" : void 0
4671
+ },
4672
+ children: /* @__PURE__ */ jsx(
4673
+ Root,
4674
+ {
4675
+ ...arrowProps,
4676
+ ref: forwardedRef,
4677
+ style: {
4678
+ ...arrowProps.style,
4679
+ // ensures the element can be measured correctly (mostly for if SVG)
4680
+ display: "block"
4681
+ }
4682
+ }
4683
+ )
4684
+ }
4685
+ )
4686
+ );
4687
+ });
4688
+ PopperArrow.displayName = ARROW_NAME$1;
4689
+ function isNotNull(value) {
4690
+ return value !== null;
4691
+ }
4692
+ var transformOrigin = (options) => ({
4693
+ name: "transformOrigin",
4694
+ options,
4695
+ fn(data) {
4696
+ const { placement, rects, middlewareData } = data;
4697
+ const cannotCenterArrow = middlewareData.arrow?.centerOffset !== 0;
4698
+ const isArrowHidden = cannotCenterArrow;
4699
+ const arrowWidth = isArrowHidden ? 0 : options.arrowWidth;
4700
+ const arrowHeight = isArrowHidden ? 0 : options.arrowHeight;
4701
+ const [placedSide, placedAlign] = getSideAndAlignFromPlacement(placement);
4702
+ const noArrowAlign = { start: "0%", center: "50%", end: "100%" }[placedAlign];
4703
+ const arrowXCenter = (middlewareData.arrow?.x ?? 0) + arrowWidth / 2;
4704
+ const arrowYCenter = (middlewareData.arrow?.y ?? 0) + arrowHeight / 2;
4705
+ let x = "";
4706
+ let y = "";
4707
+ if (placedSide === "bottom") {
4708
+ x = isArrowHidden ? noArrowAlign : `${arrowXCenter}px`;
4709
+ y = `${-arrowHeight}px`;
4710
+ } else if (placedSide === "top") {
4711
+ x = isArrowHidden ? noArrowAlign : `${arrowXCenter}px`;
4712
+ y = `${rects.floating.height + arrowHeight}px`;
4713
+ } else if (placedSide === "right") {
4714
+ x = `${-arrowHeight}px`;
4715
+ y = isArrowHidden ? noArrowAlign : `${arrowYCenter}px`;
4716
+ } else if (placedSide === "left") {
4717
+ x = `${rects.floating.width + arrowHeight}px`;
4718
+ y = isArrowHidden ? noArrowAlign : `${arrowYCenter}px`;
4719
+ }
4720
+ return { data: { x, y } };
4721
+ }
4722
+ });
4723
+ function getSideAndAlignFromPlacement(placement) {
4724
+ const [side, align = "center"] = placement.split("-");
4725
+ return [side, align];
4726
+ }
4727
+ var Root2$1 = Popper;
4728
+ var Anchor = PopperAnchor;
4729
+ var Content = PopperContent;
4730
+ var Arrow = PopperArrow;
4731
+
4732
+ var PORTAL_NAME$1 = "Portal";
4733
+ var Portal$1 = React.forwardRef((props, forwardedRef) => {
4734
+ const { container: containerProp, ...portalProps } = props;
4735
+ const [mounted, setMounted] = React.useState(false);
4736
+ useLayoutEffect2(() => setMounted(true), []);
4737
+ const container = containerProp || mounted && globalThis?.document?.body;
4738
+ return container ? ReactDOM__default.createPortal(/* @__PURE__ */ jsx(Primitive.div, { ...portalProps, ref: forwardedRef }), container) : null;
4739
+ });
4740
+ Portal$1.displayName = PORTAL_NAME$1;
4741
+
4742
+ function useStateMachine(initialState, machine) {
4743
+ return React.useReducer((state, event) => {
4744
+ const nextState = machine[state][event];
4745
+ return nextState ?? state;
4746
+ }, initialState);
4747
+ }
4748
+
4749
+ // src/presence.tsx
4750
+ var Presence = (props) => {
4751
+ const { present, children } = props;
4752
+ const presence = usePresence(present);
4753
+ const child = typeof children === "function" ? children({ present: presence.isPresent }) : React.Children.only(children);
4754
+ const ref = useComposedRefs(presence.ref, getElementRef(child));
4755
+ const forceMount = typeof children === "function";
4756
+ return forceMount || presence.isPresent ? React.cloneElement(child, { ref }) : null;
4757
+ };
4758
+ Presence.displayName = "Presence";
4759
+ function usePresence(present) {
4760
+ const [node, setNode] = React.useState();
4761
+ const stylesRef = React.useRef(null);
4762
+ const prevPresentRef = React.useRef(present);
4763
+ const prevAnimationNameRef = React.useRef("none");
4764
+ const initialState = present ? "mounted" : "unmounted";
4765
+ const [state, send] = useStateMachine(initialState, {
4766
+ mounted: {
4767
+ UNMOUNT: "unmounted",
4768
+ ANIMATION_OUT: "unmountSuspended"
4769
+ },
4770
+ unmountSuspended: {
4771
+ MOUNT: "mounted",
4772
+ ANIMATION_END: "unmounted"
4773
+ },
4774
+ unmounted: {
4775
+ MOUNT: "mounted"
4776
+ }
4777
+ });
4778
+ React.useEffect(() => {
4779
+ const currentAnimationName = getAnimationName(stylesRef.current);
4780
+ prevAnimationNameRef.current = state === "mounted" ? currentAnimationName : "none";
4781
+ }, [state]);
4782
+ useLayoutEffect2(() => {
4783
+ const styles = stylesRef.current;
4784
+ const wasPresent = prevPresentRef.current;
4785
+ const hasPresentChanged = wasPresent !== present;
4786
+ if (hasPresentChanged) {
4787
+ const prevAnimationName = prevAnimationNameRef.current;
4788
+ const currentAnimationName = getAnimationName(styles);
4789
+ if (present) {
4790
+ send("MOUNT");
4791
+ } else if (currentAnimationName === "none" || styles?.display === "none") {
4792
+ send("UNMOUNT");
4793
+ } else {
4794
+ const isAnimating = prevAnimationName !== currentAnimationName;
4795
+ if (wasPresent && isAnimating) {
4796
+ send("ANIMATION_OUT");
4797
+ } else {
4798
+ send("UNMOUNT");
4799
+ }
4800
+ }
4801
+ prevPresentRef.current = present;
4802
+ }
4803
+ }, [present, send]);
4804
+ useLayoutEffect2(() => {
4805
+ if (node) {
4806
+ let timeoutId;
4807
+ const ownerWindow = node.ownerDocument.defaultView ?? window;
4808
+ const handleAnimationEnd = (event) => {
4809
+ const currentAnimationName = getAnimationName(stylesRef.current);
4810
+ const isCurrentAnimation = currentAnimationName.includes(CSS.escape(event.animationName));
4811
+ if (event.target === node && isCurrentAnimation) {
4812
+ send("ANIMATION_END");
4813
+ if (!prevPresentRef.current) {
4814
+ const currentFillMode = node.style.animationFillMode;
4815
+ node.style.animationFillMode = "forwards";
4816
+ timeoutId = ownerWindow.setTimeout(() => {
4817
+ if (node.style.animationFillMode === "forwards") {
4818
+ node.style.animationFillMode = currentFillMode;
4819
+ }
4820
+ });
4821
+ }
4822
+ }
4823
+ };
4824
+ const handleAnimationStart = (event) => {
4825
+ if (event.target === node) {
4826
+ prevAnimationNameRef.current = getAnimationName(stylesRef.current);
4827
+ }
4828
+ };
4829
+ node.addEventListener("animationstart", handleAnimationStart);
4830
+ node.addEventListener("animationcancel", handleAnimationEnd);
4831
+ node.addEventListener("animationend", handleAnimationEnd);
4832
+ return () => {
4833
+ ownerWindow.clearTimeout(timeoutId);
4834
+ node.removeEventListener("animationstart", handleAnimationStart);
4835
+ node.removeEventListener("animationcancel", handleAnimationEnd);
4836
+ node.removeEventListener("animationend", handleAnimationEnd);
4837
+ };
4838
+ } else {
4839
+ send("ANIMATION_END");
4840
+ }
4841
+ }, [node, send]);
4842
+ return {
4843
+ isPresent: ["mounted", "unmountSuspended"].includes(state),
4844
+ ref: React.useCallback((node2) => {
4845
+ stylesRef.current = node2 ? getComputedStyle(node2) : null;
4846
+ setNode(node2);
4847
+ }, [])
4848
+ };
4849
+ }
4850
+ function getAnimationName(styles) {
4851
+ return styles?.animationName || "none";
4852
+ }
4853
+ function getElementRef(element) {
4854
+ let getter = Object.getOwnPropertyDescriptor(element.props, "ref")?.get;
4855
+ let mayWarn = getter && "isReactWarning" in getter && getter.isReactWarning;
4856
+ if (mayWarn) {
4857
+ return element.ref;
4858
+ }
4859
+ getter = Object.getOwnPropertyDescriptor(element, "ref")?.get;
4860
+ mayWarn = getter && "isReactWarning" in getter && getter.isReactWarning;
4861
+ if (mayWarn) {
4862
+ return element.props.ref;
4863
+ }
4864
+ return element.props.ref || element.ref;
4865
+ }
4866
+
4867
+ // packages/react/use-escape-keydown/src/use-escape-keydown.tsx
4868
+ function useEscapeKeydown(onEscapeKeyDownProp, ownerDocument = globalThis?.document) {
4869
+ const onEscapeKeyDown = useCallbackRef(onEscapeKeyDownProp);
4870
+ React.useEffect(() => {
4871
+ const handleKeyDown = (event) => {
4872
+ if (event.key === "Escape") {
4873
+ onEscapeKeyDown(event);
4874
+ }
4875
+ };
4876
+ ownerDocument.addEventListener("keydown", handleKeyDown, { capture: true });
4877
+ return () => ownerDocument.removeEventListener("keydown", handleKeyDown, { capture: true });
4878
+ }, [onEscapeKeyDown, ownerDocument]);
4879
+ }
4880
+
4881
+ var DISMISSABLE_LAYER_NAME = "DismissableLayer";
4882
+ var CONTEXT_UPDATE = "dismissableLayer.update";
4883
+ var POINTER_DOWN_OUTSIDE = "dismissableLayer.pointerDownOutside";
4884
+ var FOCUS_OUTSIDE = "dismissableLayer.focusOutside";
4885
+ var originalBodyPointerEvents;
4886
+ var DismissableLayerContext = React.createContext({
4887
+ layers: /* @__PURE__ */ new Set(),
4888
+ layersWithOutsidePointerEventsDisabled: /* @__PURE__ */ new Set(),
4889
+ branches: /* @__PURE__ */ new Set()
4890
+ });
4891
+ var DismissableLayer = React.forwardRef(
4892
+ (props, forwardedRef) => {
4893
+ const {
4894
+ disableOutsidePointerEvents = false,
4895
+ onEscapeKeyDown,
4896
+ onPointerDownOutside,
4897
+ onFocusOutside,
4898
+ onInteractOutside,
4899
+ onDismiss,
4900
+ ...layerProps
4901
+ } = props;
4902
+ const context = React.useContext(DismissableLayerContext);
4903
+ const [node, setNode] = React.useState(null);
4904
+ const ownerDocument = node?.ownerDocument ?? globalThis?.document;
4905
+ const [, force] = React.useState({});
4906
+ const composedRefs = useComposedRefs(forwardedRef, (node2) => setNode(node2));
4907
+ const layers = Array.from(context.layers);
4908
+ const [highestLayerWithOutsidePointerEventsDisabled] = [...context.layersWithOutsidePointerEventsDisabled].slice(-1);
4909
+ const highestLayerWithOutsidePointerEventsDisabledIndex = layers.indexOf(highestLayerWithOutsidePointerEventsDisabled);
4910
+ const index = node ? layers.indexOf(node) : -1;
4911
+ const isBodyPointerEventsDisabled = context.layersWithOutsidePointerEventsDisabled.size > 0;
4912
+ const isPointerEventsEnabled = index >= highestLayerWithOutsidePointerEventsDisabledIndex;
4913
+ const pointerDownOutside = usePointerDownOutside((event) => {
4914
+ const target = event.target;
4915
+ const isPointerDownOnBranch = [...context.branches].some((branch) => branch.contains(target));
4916
+ if (!isPointerEventsEnabled || isPointerDownOnBranch) return;
4917
+ onPointerDownOutside?.(event);
4918
+ onInteractOutside?.(event);
4919
+ if (!event.defaultPrevented) onDismiss?.();
4920
+ }, ownerDocument);
4921
+ const focusOutside = useFocusOutside((event) => {
4922
+ const target = event.target;
4923
+ const isFocusInBranch = [...context.branches].some((branch) => branch.contains(target));
4924
+ if (isFocusInBranch) return;
4925
+ onFocusOutside?.(event);
4926
+ onInteractOutside?.(event);
4927
+ if (!event.defaultPrevented) onDismiss?.();
4928
+ }, ownerDocument);
4929
+ useEscapeKeydown((event) => {
4930
+ const isHighestLayer = index === context.layers.size - 1;
4931
+ if (!isHighestLayer) return;
4932
+ onEscapeKeyDown?.(event);
4933
+ if (!event.defaultPrevented && onDismiss) {
4934
+ event.preventDefault();
4935
+ onDismiss();
4936
+ }
4937
+ }, ownerDocument);
2111
4938
  React.useEffect(() => {
2112
- if (isVisible) {
2113
- calculatePosition();
2114
- window.addEventListener("scroll", calculatePosition, true);
2115
- window.addEventListener("resize", calculatePosition);
2116
- }
2117
- return () => {
2118
- window.removeEventListener("scroll", calculatePosition, true);
2119
- window.removeEventListener("resize", calculatePosition);
2120
- };
2121
- }, [isVisible, calculatePosition]);
4939
+ if (!node) return;
4940
+ if (disableOutsidePointerEvents) {
4941
+ if (context.layersWithOutsidePointerEventsDisabled.size === 0) {
4942
+ originalBodyPointerEvents = ownerDocument.body.style.pointerEvents;
4943
+ ownerDocument.body.style.pointerEvents = "none";
4944
+ }
4945
+ context.layersWithOutsidePointerEventsDisabled.add(node);
4946
+ }
4947
+ context.layers.add(node);
4948
+ dispatchUpdate();
4949
+ return () => {
4950
+ if (disableOutsidePointerEvents && context.layersWithOutsidePointerEventsDisabled.size === 1) {
4951
+ ownerDocument.body.style.pointerEvents = originalBodyPointerEvents;
4952
+ }
4953
+ };
4954
+ }, [node, ownerDocument, disableOutsidePointerEvents, context]);
2122
4955
  React.useEffect(() => {
2123
- // Reset actualPlacement when placement prop changes
2124
- setActualPlacement(placement);
2125
- }, [placement]);
4956
+ return () => {
4957
+ if (!node) return;
4958
+ context.layers.delete(node);
4959
+ context.layersWithOutsidePointerEventsDisabled.delete(node);
4960
+ dispatchUpdate();
4961
+ };
4962
+ }, [node, context]);
2126
4963
  React.useEffect(() => {
2127
- return () => {
2128
- if (timeoutRef.current) {
2129
- clearTimeout(timeoutRef.current);
2130
- }
2131
- };
4964
+ const handleUpdate = () => force({});
4965
+ document.addEventListener(CONTEXT_UPDATE, handleUpdate);
4966
+ return () => document.removeEventListener(CONTEXT_UPDATE, handleUpdate);
2132
4967
  }, []);
2133
- // Merge refs function
2134
- const mergeRefs = (...refs) => {
2135
- return (node) => {
2136
- refs.forEach((ref) => {
2137
- if (typeof ref === "function") {
2138
- ref(node);
2139
- }
2140
- else if (ref && typeof ref === "object" && "current" in ref) {
2141
- ref.current = node;
2142
- }
2143
- });
4968
+ return /* @__PURE__ */ jsx(
4969
+ Primitive.div,
4970
+ {
4971
+ ...layerProps,
4972
+ ref: composedRefs,
4973
+ style: {
4974
+ pointerEvents: isBodyPointerEventsDisabled ? isPointerEventsEnabled ? "auto" : "none" : void 0,
4975
+ ...props.style
4976
+ },
4977
+ onFocusCapture: composeEventHandlers(props.onFocusCapture, focusOutside.onFocusCapture),
4978
+ onBlurCapture: composeEventHandlers(props.onBlurCapture, focusOutside.onBlurCapture),
4979
+ onPointerDownCapture: composeEventHandlers(
4980
+ props.onPointerDownCapture,
4981
+ pointerDownOutside.onPointerDownCapture
4982
+ )
4983
+ }
4984
+ );
4985
+ }
4986
+ );
4987
+ DismissableLayer.displayName = DISMISSABLE_LAYER_NAME;
4988
+ var BRANCH_NAME = "DismissableLayerBranch";
4989
+ var DismissableLayerBranch = React.forwardRef((props, forwardedRef) => {
4990
+ const context = React.useContext(DismissableLayerContext);
4991
+ const ref = React.useRef(null);
4992
+ const composedRefs = useComposedRefs(forwardedRef, ref);
4993
+ React.useEffect(() => {
4994
+ const node = ref.current;
4995
+ if (node) {
4996
+ context.branches.add(node);
4997
+ return () => {
4998
+ context.branches.delete(node);
4999
+ };
5000
+ }
5001
+ }, [context.branches]);
5002
+ return /* @__PURE__ */ jsx(Primitive.div, { ...props, ref: composedRefs });
5003
+ });
5004
+ DismissableLayerBranch.displayName = BRANCH_NAME;
5005
+ function usePointerDownOutside(onPointerDownOutside, ownerDocument = globalThis?.document) {
5006
+ const handlePointerDownOutside = useCallbackRef(onPointerDownOutside);
5007
+ const isPointerInsideReactTreeRef = React.useRef(false);
5008
+ const handleClickRef = React.useRef(() => {
5009
+ });
5010
+ React.useEffect(() => {
5011
+ const handlePointerDown = (event) => {
5012
+ if (event.target && !isPointerInsideReactTreeRef.current) {
5013
+ let handleAndDispatchPointerDownOutsideEvent2 = function() {
5014
+ handleAndDispatchCustomEvent(
5015
+ POINTER_DOWN_OUTSIDE,
5016
+ handlePointerDownOutside,
5017
+ eventDetail,
5018
+ { discrete: true }
5019
+ );
2144
5020
  };
5021
+ const eventDetail = { originalEvent: event };
5022
+ if (event.pointerType === "touch") {
5023
+ ownerDocument.removeEventListener("click", handleClickRef.current);
5024
+ handleClickRef.current = handleAndDispatchPointerDownOutsideEvent2;
5025
+ ownerDocument.addEventListener("click", handleClickRef.current, { once: true });
5026
+ } else {
5027
+ handleAndDispatchPointerDownOutsideEvent2();
5028
+ }
5029
+ } else {
5030
+ ownerDocument.removeEventListener("click", handleClickRef.current);
5031
+ }
5032
+ isPointerInsideReactTreeRef.current = false;
2145
5033
  };
2146
- // Clone the child element and add event handlers
2147
- const trigger = React.cloneElement(children, {
2148
- ref: mergeRefs(triggerRef, children.ref),
2149
- onMouseEnter: (e) => {
2150
- handleMouseEnter();
2151
- children.props.onMouseEnter?.(e);
2152
- },
2153
- onMouseLeave: (e) => {
2154
- handleMouseLeave();
2155
- children.props.onMouseLeave?.(e);
2156
- },
2157
- onFocus: (e) => {
2158
- handleFocus();
2159
- children.props.onFocus?.(e);
2160
- },
2161
- onBlur: (e) => {
2162
- handleBlur();
2163
- children.props.onBlur?.(e);
2164
- },
2165
- "aria-describedby": isVisible ? "tooltip-content" : undefined,
2166
- });
2167
- return (jsxs(Fragment, { children: [trigger, jsxs("div", { ref: mergeRefs(tooltipRef, ref), id: "tooltip-content", role: "tooltip", className: cn(tooltipVariants({ isVisible }), className), style: {
2168
- top: `${position.top}px`,
2169
- left: `${position.left}px`,
2170
- }, "aria-hidden": !isVisible, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, children: [showArrow && (jsx("div", { className: cn(tooltipArrowVariants({ placement: actualPlacement })), style: {
2171
- left: `${arrowPosition.left}px`,
2172
- } })), jsxs("div", { className: "relative flex flex-col gap-2", children: [heading && (jsx(Text, { variant: "body", size: "medium", weight: "semibold", color: "onPrimary", children: heading })), jsx(Text, { variant: "body", size: "small", weight: "regular", color: "onPrimary", children: description })] })] })] }));
5034
+ const timerId = window.setTimeout(() => {
5035
+ ownerDocument.addEventListener("pointerdown", handlePointerDown);
5036
+ }, 0);
5037
+ return () => {
5038
+ window.clearTimeout(timerId);
5039
+ ownerDocument.removeEventListener("pointerdown", handlePointerDown);
5040
+ ownerDocument.removeEventListener("click", handleClickRef.current);
5041
+ };
5042
+ }, [ownerDocument, handlePointerDownOutside]);
5043
+ return {
5044
+ // ensures we check React component tree (not just DOM tree)
5045
+ onPointerDownCapture: () => isPointerInsideReactTreeRef.current = true
5046
+ };
5047
+ }
5048
+ function useFocusOutside(onFocusOutside, ownerDocument = globalThis?.document) {
5049
+ const handleFocusOutside = useCallbackRef(onFocusOutside);
5050
+ const isFocusInsideReactTreeRef = React.useRef(false);
5051
+ React.useEffect(() => {
5052
+ const handleFocus = (event) => {
5053
+ if (event.target && !isFocusInsideReactTreeRef.current) {
5054
+ const eventDetail = { originalEvent: event };
5055
+ handleAndDispatchCustomEvent(FOCUS_OUTSIDE, handleFocusOutside, eventDetail, {
5056
+ discrete: false
5057
+ });
5058
+ }
5059
+ };
5060
+ ownerDocument.addEventListener("focusin", handleFocus);
5061
+ return () => ownerDocument.removeEventListener("focusin", handleFocus);
5062
+ }, [ownerDocument, handleFocusOutside]);
5063
+ return {
5064
+ onFocusCapture: () => isFocusInsideReactTreeRef.current = true,
5065
+ onBlurCapture: () => isFocusInsideReactTreeRef.current = false
5066
+ };
5067
+ }
5068
+ function dispatchUpdate() {
5069
+ const event = new CustomEvent(CONTEXT_UPDATE);
5070
+ document.dispatchEvent(event);
5071
+ }
5072
+ function handleAndDispatchCustomEvent(name, handler, detail, { discrete }) {
5073
+ const target = detail.originalEvent.target;
5074
+ const event = new CustomEvent(name, { bubbles: false, cancelable: true, detail });
5075
+ if (handler) target.addEventListener(name, handler, { once: true });
5076
+ if (discrete) {
5077
+ dispatchDiscreteCustomEvent(target, event);
5078
+ } else {
5079
+ target.dispatchEvent(event);
5080
+ }
5081
+ }
5082
+
5083
+ var originalBodyUserSelect;
5084
+ var HOVERCARD_NAME = "HoverCard";
5085
+ var [createHoverCardContext] = createContextScope(HOVERCARD_NAME, [
5086
+ createPopperScope
5087
+ ]);
5088
+ var usePopperScope = createPopperScope();
5089
+ var [HoverCardProvider, useHoverCardContext] = createHoverCardContext(HOVERCARD_NAME);
5090
+ var HoverCard = (props) => {
5091
+ const {
5092
+ __scopeHoverCard,
5093
+ children,
5094
+ open: openProp,
5095
+ defaultOpen,
5096
+ onOpenChange,
5097
+ openDelay = 700,
5098
+ closeDelay = 300
5099
+ } = props;
5100
+ const popperScope = usePopperScope(__scopeHoverCard);
5101
+ const openTimerRef = React.useRef(0);
5102
+ const closeTimerRef = React.useRef(0);
5103
+ const hasSelectionRef = React.useRef(false);
5104
+ const isPointerDownOnContentRef = React.useRef(false);
5105
+ const [open, setOpen] = useControllableState({
5106
+ prop: openProp,
5107
+ defaultProp: defaultOpen ?? false,
5108
+ onChange: onOpenChange,
5109
+ caller: HOVERCARD_NAME
5110
+ });
5111
+ const handleOpen = React.useCallback(() => {
5112
+ clearTimeout(closeTimerRef.current);
5113
+ openTimerRef.current = window.setTimeout(() => setOpen(true), openDelay);
5114
+ }, [openDelay, setOpen]);
5115
+ const handleClose = React.useCallback(() => {
5116
+ clearTimeout(openTimerRef.current);
5117
+ if (!hasSelectionRef.current && !isPointerDownOnContentRef.current) {
5118
+ closeTimerRef.current = window.setTimeout(() => setOpen(false), closeDelay);
5119
+ }
5120
+ }, [closeDelay, setOpen]);
5121
+ const handleDismiss = React.useCallback(() => setOpen(false), [setOpen]);
5122
+ React.useEffect(() => {
5123
+ return () => {
5124
+ clearTimeout(openTimerRef.current);
5125
+ clearTimeout(closeTimerRef.current);
5126
+ };
5127
+ }, []);
5128
+ return /* @__PURE__ */ jsx(
5129
+ HoverCardProvider,
5130
+ {
5131
+ scope: __scopeHoverCard,
5132
+ open,
5133
+ onOpenChange: setOpen,
5134
+ onOpen: handleOpen,
5135
+ onClose: handleClose,
5136
+ onDismiss: handleDismiss,
5137
+ hasSelectionRef,
5138
+ isPointerDownOnContentRef,
5139
+ children: /* @__PURE__ */ jsx(Root2$1, { ...popperScope, children })
5140
+ }
5141
+ );
5142
+ };
5143
+ HoverCard.displayName = HOVERCARD_NAME;
5144
+ var TRIGGER_NAME = "HoverCardTrigger";
5145
+ var HoverCardTrigger = React.forwardRef(
5146
+ (props, forwardedRef) => {
5147
+ const { __scopeHoverCard, ...triggerProps } = props;
5148
+ const context = useHoverCardContext(TRIGGER_NAME, __scopeHoverCard);
5149
+ const popperScope = usePopperScope(__scopeHoverCard);
5150
+ return /* @__PURE__ */ jsx(Anchor, { asChild: true, ...popperScope, children: /* @__PURE__ */ jsx(
5151
+ Primitive.a,
5152
+ {
5153
+ "data-state": context.open ? "open" : "closed",
5154
+ ...triggerProps,
5155
+ ref: forwardedRef,
5156
+ onPointerEnter: composeEventHandlers(props.onPointerEnter, excludeTouch(context.onOpen)),
5157
+ onPointerLeave: composeEventHandlers(props.onPointerLeave, excludeTouch(context.onClose)),
5158
+ onFocus: composeEventHandlers(props.onFocus, context.onOpen),
5159
+ onBlur: composeEventHandlers(props.onBlur, context.onClose),
5160
+ onTouchStart: composeEventHandlers(props.onTouchStart, (event) => event.preventDefault())
5161
+ }
5162
+ ) });
5163
+ }
5164
+ );
5165
+ HoverCardTrigger.displayName = TRIGGER_NAME;
5166
+ var PORTAL_NAME = "HoverCardPortal";
5167
+ var [PortalProvider, usePortalContext] = createHoverCardContext(PORTAL_NAME, {
5168
+ forceMount: void 0
5169
+ });
5170
+ var HoverCardPortal = (props) => {
5171
+ const { __scopeHoverCard, forceMount, children, container } = props;
5172
+ const context = useHoverCardContext(PORTAL_NAME, __scopeHoverCard);
5173
+ return /* @__PURE__ */ jsx(PortalProvider, { scope: __scopeHoverCard, forceMount, children: /* @__PURE__ */ jsx(Presence, { present: forceMount || context.open, children: /* @__PURE__ */ jsx(Portal$1, { asChild: true, container, children }) }) });
5174
+ };
5175
+ HoverCardPortal.displayName = PORTAL_NAME;
5176
+ var CONTENT_NAME = "HoverCardContent";
5177
+ var HoverCardContent = React.forwardRef(
5178
+ (props, forwardedRef) => {
5179
+ const portalContext = usePortalContext(CONTENT_NAME, props.__scopeHoverCard);
5180
+ const { forceMount = portalContext.forceMount, ...contentProps } = props;
5181
+ const context = useHoverCardContext(CONTENT_NAME, props.__scopeHoverCard);
5182
+ return /* @__PURE__ */ jsx(Presence, { present: forceMount || context.open, children: /* @__PURE__ */ jsx(
5183
+ HoverCardContentImpl,
5184
+ {
5185
+ "data-state": context.open ? "open" : "closed",
5186
+ ...contentProps,
5187
+ onPointerEnter: composeEventHandlers(props.onPointerEnter, excludeTouch(context.onOpen)),
5188
+ onPointerLeave: composeEventHandlers(props.onPointerLeave, excludeTouch(context.onClose)),
5189
+ ref: forwardedRef
5190
+ }
5191
+ ) });
5192
+ }
5193
+ );
5194
+ HoverCardContent.displayName = CONTENT_NAME;
5195
+ var HoverCardContentImpl = React.forwardRef((props, forwardedRef) => {
5196
+ const {
5197
+ __scopeHoverCard,
5198
+ onEscapeKeyDown,
5199
+ onPointerDownOutside,
5200
+ onFocusOutside,
5201
+ onInteractOutside,
5202
+ ...contentProps
5203
+ } = props;
5204
+ const context = useHoverCardContext(CONTENT_NAME, __scopeHoverCard);
5205
+ const popperScope = usePopperScope(__scopeHoverCard);
5206
+ const ref = React.useRef(null);
5207
+ const composedRefs = useComposedRefs(forwardedRef, ref);
5208
+ const [containSelection, setContainSelection] = React.useState(false);
5209
+ React.useEffect(() => {
5210
+ if (containSelection) {
5211
+ const body = document.body;
5212
+ originalBodyUserSelect = body.style.userSelect || body.style.webkitUserSelect;
5213
+ body.style.userSelect = "none";
5214
+ body.style.webkitUserSelect = "none";
5215
+ return () => {
5216
+ body.style.userSelect = originalBodyUserSelect;
5217
+ body.style.webkitUserSelect = originalBodyUserSelect;
5218
+ };
5219
+ }
5220
+ }, [containSelection]);
5221
+ React.useEffect(() => {
5222
+ if (ref.current) {
5223
+ const handlePointerUp = () => {
5224
+ setContainSelection(false);
5225
+ context.isPointerDownOnContentRef.current = false;
5226
+ setTimeout(() => {
5227
+ const hasSelection = document.getSelection()?.toString() !== "";
5228
+ if (hasSelection) context.hasSelectionRef.current = true;
5229
+ });
5230
+ };
5231
+ document.addEventListener("pointerup", handlePointerUp);
5232
+ return () => {
5233
+ document.removeEventListener("pointerup", handlePointerUp);
5234
+ context.hasSelectionRef.current = false;
5235
+ context.isPointerDownOnContentRef.current = false;
5236
+ };
5237
+ }
5238
+ }, [context.isPointerDownOnContentRef, context.hasSelectionRef]);
5239
+ React.useEffect(() => {
5240
+ if (ref.current) {
5241
+ const tabbables = getTabbableNodes(ref.current);
5242
+ tabbables.forEach((tabbable) => tabbable.setAttribute("tabindex", "-1"));
5243
+ }
5244
+ });
5245
+ return /* @__PURE__ */ jsx(
5246
+ DismissableLayer,
5247
+ {
5248
+ asChild: true,
5249
+ disableOutsidePointerEvents: false,
5250
+ onInteractOutside,
5251
+ onEscapeKeyDown,
5252
+ onPointerDownOutside,
5253
+ onFocusOutside: composeEventHandlers(onFocusOutside, (event) => {
5254
+ event.preventDefault();
5255
+ }),
5256
+ onDismiss: context.onDismiss,
5257
+ children: /* @__PURE__ */ jsx(
5258
+ Content,
5259
+ {
5260
+ ...popperScope,
5261
+ ...contentProps,
5262
+ onPointerDown: composeEventHandlers(contentProps.onPointerDown, (event) => {
5263
+ if (event.currentTarget.contains(event.target)) {
5264
+ setContainSelection(true);
5265
+ }
5266
+ context.hasSelectionRef.current = false;
5267
+ context.isPointerDownOnContentRef.current = true;
5268
+ }),
5269
+ ref: composedRefs,
5270
+ style: {
5271
+ ...contentProps.style,
5272
+ userSelect: containSelection ? "text" : void 0,
5273
+ // Safari requires prefix
5274
+ WebkitUserSelect: containSelection ? "text" : void 0,
5275
+ // re-namespace exposed content custom properties
5276
+ ...{
5277
+ "--radix-hover-card-content-transform-origin": "var(--radix-popper-transform-origin)",
5278
+ "--radix-hover-card-content-available-width": "var(--radix-popper-available-width)",
5279
+ "--radix-hover-card-content-available-height": "var(--radix-popper-available-height)",
5280
+ "--radix-hover-card-trigger-width": "var(--radix-popper-anchor-width)",
5281
+ "--radix-hover-card-trigger-height": "var(--radix-popper-anchor-height)"
5282
+ }
5283
+ }
5284
+ }
5285
+ )
5286
+ }
5287
+ );
5288
+ });
5289
+ var ARROW_NAME = "HoverCardArrow";
5290
+ var HoverCardArrow = React.forwardRef(
5291
+ (props, forwardedRef) => {
5292
+ const { __scopeHoverCard, ...arrowProps } = props;
5293
+ const popperScope = usePopperScope(__scopeHoverCard);
5294
+ return /* @__PURE__ */ jsx(Arrow, { ...popperScope, ...arrowProps, ref: forwardedRef });
5295
+ }
5296
+ );
5297
+ HoverCardArrow.displayName = ARROW_NAME;
5298
+ function excludeTouch(eventHandler) {
5299
+ return (event) => event.pointerType === "touch" ? void 0 : eventHandler();
5300
+ }
5301
+ function getTabbableNodes(container) {
5302
+ const nodes = [];
5303
+ const walker = document.createTreeWalker(container, NodeFilter.SHOW_ELEMENT, {
5304
+ acceptNode: (node) => {
5305
+ return node.tabIndex >= 0 ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
5306
+ }
5307
+ });
5308
+ while (walker.nextNode()) nodes.push(walker.currentNode);
5309
+ return nodes;
5310
+ }
5311
+ var Root2 = HoverCard;
5312
+ var Trigger = HoverCardTrigger;
5313
+ var Portal = HoverCardPortal;
5314
+ var Content2 = HoverCardContent;
5315
+ var Arrow2 = HoverCardArrow;
5316
+
5317
+ const tooltipVariants = cva("z-[9998] bg-popup-fill-intense text-action-ink-on-primary-normal border border-popup-outline-subtle flex flex-col p-4 rounded-xlarge min-w-[200px] max-w-[300px] shadow-[0_4px_20px_rgba(0,0,0,0.15)]");
5318
+ const Tooltip = React.forwardRef(({ children, heading, description, placement = "top", showArrow = true, className, delay = 200, disabled = false, }, ref) => {
5319
+ const { side, align } = React.useMemo(() => {
5320
+ switch (placement) {
5321
+ case "top-start":
5322
+ return { side: "top", align: "start" };
5323
+ case "top-end":
5324
+ return { side: "top", align: "end" };
5325
+ case "bottom-start":
5326
+ return { side: "bottom", align: "start" };
5327
+ case "bottom-end":
5328
+ return { side: "bottom", align: "end" };
5329
+ case "bottom":
5330
+ return { side: "bottom", align: "center" };
5331
+ case "top":
5332
+ default:
5333
+ return { side: "top", align: "center" };
5334
+ }
5335
+ }, [placement]);
5336
+ if (disabled) {
5337
+ return children;
5338
+ }
5339
+ return (jsxs(Root2, { openDelay: delay, closeDelay: 250, children: [jsx(Trigger, { asChild: true, children: children }), jsx(Portal, { children: jsxs(Content2, { ref: ref, role: "tooltip", side: side, align: align, sideOffset: 14, collisionPadding: 8, className: cn(tooltipVariants(), className), children: [showArrow && (jsx(Arrow2, { width: 12, height: 6, className: "fill-popup-fill-intense" })), jsxs("div", { className: "relative flex flex-col gap-2", children: [heading && (jsx(Text, { variant: "body", size: "medium", weight: "semibold", color: "onPrimary", children: heading })), jsx(Text, { variant: "body", size: "small", weight: "regular", color: "onPrimary", children: description })] })] }) })] }));
2173
5340
  });
2174
5341
  Tooltip.displayName = "Tooltip";
2175
5342