@via-profit/ui-kit 0.2.4 → 0.2.5
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/Autocomplete/AutocompleteContainer.d.ts +2 -1
- package/Calendar/CalendarComponent.d.ts +2 -0
- package/Calendar/CalendarComponent.js +10 -3
- package/Calendar/use-calendar.d.ts +1 -1
- package/package.json +1 -1
- package/Autocomplete/AutocompleteTextField.d.ts +0 -18
- package/Autocomplete/AutocompleteTextField.js +0 -71
- package/Highlighted/splitTextIntoParts.d.ts +0 -5
- package/Highlighted/splitTextIntoParts.js +0 -46
- package/Popper/usePopprer.d.ts +0 -110
- package/Popper/usePopprer.js +0 -505
|
@@ -2,7 +2,8 @@ import React from 'react';
|
|
|
2
2
|
import { TextFieldProps } from '../TextField';
|
|
3
3
|
import { PositionStrategy } from '../Popper';
|
|
4
4
|
import { AnchorPos, GetOptionSelected, MenuItemProps, OnRequestClose, Value } from '../Menu';
|
|
5
|
-
export
|
|
5
|
+
export type AutocompleteTextFieldProps = Omit<TextFieldProps, 'value' | 'onChange' | 'children' | 'overrides'>;
|
|
6
|
+
export interface AutocompleteProps<T, Multiple extends boolean | undefined = undefined> extends AutocompleteTextFieldProps {
|
|
6
7
|
readonly items: readonly T[];
|
|
7
8
|
readonly value: Value<T, Multiple>;
|
|
8
9
|
/**
|
|
@@ -217,9 +217,11 @@ export type CalendarBadge = {
|
|
|
217
217
|
};
|
|
218
218
|
export type CalendarRef<IsRangeValue extends boolean | undefined = undefined> = {
|
|
219
219
|
readonly setView: (view: CalendarView) => void;
|
|
220
|
+
readonly setViews: (views: readonly CalendarView[]) => void;
|
|
220
221
|
readonly getActiveView: () => CalendarView;
|
|
221
222
|
readonly setValue: (value: CalendarValue<IsRangeValue>) => void;
|
|
222
223
|
readonly setCalendarDate: (date: Date) => void;
|
|
224
|
+
readonly getCalendarDate: () => Date;
|
|
223
225
|
readonly reset: () => void;
|
|
224
226
|
};
|
|
225
227
|
declare const CalendarComponent: React.ForwardRefExoticComponent<CalendarProps<boolean | undefined> & React.RefAttributes<CalendarRef<boolean | undefined>>>;
|
|
@@ -199,15 +199,19 @@ const CalendarComponent = react_1.default.forwardRef((props, ref) => {
|
|
|
199
199
|
/**
|
|
200
200
|
* List of possibility views
|
|
201
201
|
*/
|
|
202
|
-
const [views] = react_1.default.useState(() => computeViews(inputViews, range));
|
|
202
|
+
const [views, setComputedViews] = react_1.default.useState(() => computeViews(inputViews, range));
|
|
203
|
+
const setViews = react_1.default.useCallback((variants) => setComputedViews(variants), []);
|
|
203
204
|
const selectView = react_1.default.useCallback((view) => {
|
|
204
205
|
var _a;
|
|
206
|
+
if (!views.includes(view)) {
|
|
207
|
+
setViews([...views, view]);
|
|
208
|
+
}
|
|
205
209
|
setView(view);
|
|
206
210
|
const index = views.findIndex(v => v === view);
|
|
207
211
|
if (index > -1) {
|
|
208
212
|
(_a = swiperRef.current) === null || _a === void 0 ? void 0 : _a.goToIndex(index);
|
|
209
213
|
}
|
|
210
|
-
}, [views]);
|
|
214
|
+
}, [setViews, views]);
|
|
211
215
|
const resetVariablesRef = react_1.default.useRef({
|
|
212
216
|
calendarDate,
|
|
213
217
|
value,
|
|
@@ -503,6 +507,7 @@ const CalendarComponent = react_1.default.forwardRef((props, ref) => {
|
|
|
503
507
|
]);
|
|
504
508
|
const initialIndex = react_1.default.useMemo(() => views.findIndex(v => v === view), [views, view]);
|
|
505
509
|
const getActiveView = react_1.default.useCallback(() => view, [view]);
|
|
510
|
+
const getCalendarDate = react_1.default.useCallback(() => calendarDate, [calendarDate]);
|
|
506
511
|
/**
|
|
507
512
|
* API
|
|
508
513
|
*/
|
|
@@ -510,9 +515,11 @@ const CalendarComponent = react_1.default.forwardRef((props, ref) => {
|
|
|
510
515
|
setView: selectView,
|
|
511
516
|
reset: handleReset,
|
|
512
517
|
setValue,
|
|
518
|
+
getCalendarDate,
|
|
513
519
|
setCalendarDate,
|
|
514
520
|
getActiveView,
|
|
515
|
-
|
|
521
|
+
setViews,
|
|
522
|
+
}), [selectView, handleReset, getActiveView, setViews, getCalendarDate]);
|
|
516
523
|
return (react_1.default.createElement(overridesMap.Paper, null,
|
|
517
524
|
react_1.default.createElement(overridesMap.Header, null,
|
|
518
525
|
typeof heading !== 'undefined' && react_1.default.createElement(overridesMap.Heading, null, heading),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type CalendarValue<Range> = Range extends undefined ? Date | null : [Date, Date] | [Date | null] | null;
|
|
1
|
+
export type CalendarValue<Range> = Range extends undefined ? Date | null : [Date, Date] | [Date, Date | null] | null;
|
|
2
2
|
export type WeekDayName = 'sunday' | 'monday' | 'tuesday' | 'wednesday' | 'thursday' | 'friday' | 'saturday';
|
|
3
3
|
export type Day = {
|
|
4
4
|
readonly date: Date;
|
package/package.json
CHANGED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { TextFieldProps } from '../TextField';
|
|
3
|
-
import { AnchorPos } from '../Menu';
|
|
4
|
-
export interface AutocompleteTextFieldProps extends TextFieldProps {
|
|
5
|
-
/**
|
|
6
|
-
* Text field loading state\
|
|
7
|
-
* If `true` then text field has been contained the loading indicator, otherwise - nop
|
|
8
|
-
*/
|
|
9
|
-
readonly isLoading?: boolean;
|
|
10
|
-
readonly anchorPos?: AnchorPos;
|
|
11
|
-
readonly isOpen?: boolean;
|
|
12
|
-
/**
|
|
13
|
-
* Native <input> element reference
|
|
14
|
-
*/
|
|
15
|
-
readonly inputRef?: React.MutableRefObject<HTMLInputElement | null> | React.RefCallback<HTMLInputElement>;
|
|
16
|
-
}
|
|
17
|
-
declare const _default: React.ForwardRefExoticComponent<AutocompleteTextFieldProps & React.RefAttributes<HTMLDivElement>>;
|
|
18
|
-
export default _default;
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
-
var t = {};
|
|
4
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
-
t[p] = s[p];
|
|
6
|
-
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
-
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
-
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
-
t[p[i]] = s[p[i]];
|
|
10
|
-
}
|
|
11
|
-
return t;
|
|
12
|
-
};
|
|
13
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
|
-
};
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
const react_1 = __importDefault(require("react"));
|
|
18
|
-
const styled_1 = __importDefault(require("@emotion/styled"));
|
|
19
|
-
const react_2 = require("@emotion/react");
|
|
20
|
-
const TextField_1 = __importDefault(require("../TextField"));
|
|
21
|
-
const TextFieldInputWrapper_1 = __importDefault(require("../TextField/TextFieldInputWrapper"));
|
|
22
|
-
const StyledTextFieldInputWrapper = (0, styled_1.default)(TextFieldInputWrapper_1.default) `
|
|
23
|
-
${({ theme, $isOpen, $anchorPos }) => $isOpen &&
|
|
24
|
-
$anchorPos &&
|
|
25
|
-
['bottom-fill', 'top-fill'].includes($anchorPos) &&
|
|
26
|
-
(0, react_2.css) `
|
|
27
|
-
border-width: 1px;
|
|
28
|
-
border-style: solid;
|
|
29
|
-
border-color: ${theme.isDark
|
|
30
|
-
? theme.color.textPrimary.darken(100).toString()
|
|
31
|
-
: theme.color.textPrimary.lighten(150).toString()};
|
|
32
|
-
`};
|
|
33
|
-
|
|
34
|
-
${({ focused, $anchorPos, $isOpen }) => $isOpen &&
|
|
35
|
-
$anchorPos &&
|
|
36
|
-
['bottom-fill', 'top-fill'].includes($anchorPos) &&
|
|
37
|
-
focused &&
|
|
38
|
-
(0, react_2.css) `
|
|
39
|
-
outline: none;
|
|
40
|
-
`};
|
|
41
|
-
|
|
42
|
-
${({ $anchorPos, $isOpen }) => $isOpen &&
|
|
43
|
-
$anchorPos === 'bottom-fill' &&
|
|
44
|
-
(0, react_2.css) `
|
|
45
|
-
border-bottom-left-radius: 0;
|
|
46
|
-
border-bottom-right-radius: 0;
|
|
47
|
-
border-bottom: 0;
|
|
48
|
-
`};
|
|
49
|
-
|
|
50
|
-
${({ $anchorPos, $isOpen }) => $isOpen &&
|
|
51
|
-
$anchorPos === 'top-fill' &&
|
|
52
|
-
(0, react_2.css) `
|
|
53
|
-
border-top-left-radius: 0;
|
|
54
|
-
border-top-right-radius: 0;
|
|
55
|
-
border-top: 0;
|
|
56
|
-
`};
|
|
57
|
-
`;
|
|
58
|
-
const WrapperContext = react_1.default.createContext({ anchorPos: undefined, isOpen: false });
|
|
59
|
-
const InputWrapper = react_1.default.forwardRef(function StyledInputWrapper(props, ref) {
|
|
60
|
-
const ctx = react_1.default.useContext(WrapperContext);
|
|
61
|
-
const { anchorPos, isOpen } = ctx;
|
|
62
|
-
return (react_1.default.createElement(StyledTextFieldInputWrapper, Object.assign({ "$anchorPos": anchorPos, "$isOpen": isOpen, ref: ref }, props)));
|
|
63
|
-
});
|
|
64
|
-
const AutocompleteTextField = (props, ref) => {
|
|
65
|
-
const { anchorPos, isOpen } = props, restProps = __rest(props, ["anchorPos", "isOpen"]);
|
|
66
|
-
return (react_1.default.createElement(WrapperContext.Provider, { value: { anchorPos, isOpen } },
|
|
67
|
-
react_1.default.createElement(TextField_1.default, Object.assign({ overrides: {
|
|
68
|
-
InputWrapper,
|
|
69
|
-
} }, restProps, { ref: ref }))));
|
|
70
|
-
};
|
|
71
|
-
exports.default = react_1.default.forwardRef(AutocompleteTextField);
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.splitTextIntoParts = void 0;
|
|
4
|
-
const MAX_MATCHES = 1000;
|
|
5
|
-
const splitTextIntoParts = (text, regex, patterns) => {
|
|
6
|
-
if (patterns.length === 0) {
|
|
7
|
-
return [{ text, highlighted: false }];
|
|
8
|
-
}
|
|
9
|
-
const parts = [];
|
|
10
|
-
let lastIndex = 0;
|
|
11
|
-
let match;
|
|
12
|
-
let matchCount = 0;
|
|
13
|
-
const cleanRegex = new RegExp(regex.source, regex.flags);
|
|
14
|
-
while ((match = cleanRegex.exec(text)) !== null) {
|
|
15
|
-
matchCount++;
|
|
16
|
-
if (matchCount > MAX_MATCHES) {
|
|
17
|
-
console.warn(`splitTextIntoParts: Too many matches (${matchCount}), stopping at ${MAX_MATCHES} matches`);
|
|
18
|
-
break;
|
|
19
|
-
}
|
|
20
|
-
const matchStart = match.index;
|
|
21
|
-
const matchEnd = matchStart + match[0].length;
|
|
22
|
-
if (matchStart > lastIndex) {
|
|
23
|
-
parts.push({
|
|
24
|
-
text: text.substring(lastIndex, matchStart),
|
|
25
|
-
highlighted: false,
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
parts.push({
|
|
29
|
-
text: match[0],
|
|
30
|
-
highlighted: true,
|
|
31
|
-
});
|
|
32
|
-
lastIndex = matchEnd;
|
|
33
|
-
if (match[0].length === 0) {
|
|
34
|
-
break;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
if (lastIndex < text.length) {
|
|
38
|
-
parts.push({
|
|
39
|
-
text: text.substring(lastIndex),
|
|
40
|
-
highlighted: false,
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
return parts;
|
|
44
|
-
};
|
|
45
|
-
exports.splitTextIntoParts = splitTextIntoParts;
|
|
46
|
-
exports.default = exports.splitTextIntoParts;
|
package/Popper/usePopprer.d.ts
DELETED
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { PositionStrategy } from './PopperContainer';
|
|
3
|
-
/**
|
|
4
|
-
* Base directions for popper positioning.
|
|
5
|
-
* These are the primary axes around which the popper can be placed.
|
|
6
|
-
*
|
|
7
|
-
* @default 'bottom' (when used as anchorPos)
|
|
8
|
-
* @example
|
|
9
|
-
* ```tsx
|
|
10
|
-
* type Direction = 'top' | 'bottom' | 'left' | 'right';
|
|
11
|
-
* ```
|
|
12
|
-
*/
|
|
13
|
-
export type Direction = 'top' | 'left' | 'right' | 'bottom';
|
|
14
|
-
/**
|
|
15
|
-
* Auto placement modifiers that enable intelligent positioning.
|
|
16
|
-
* The popper will automatically choose the best placement that fits in the viewport.
|
|
17
|
-
* - `auto`: Dynamically selects the optimal direction
|
|
18
|
-
* - `auto-top`, `auto-bottom`, `auto-left`, `auto-right`: Auto placement with priority given to the specified direction
|
|
19
|
-
*
|
|
20
|
-
* @example
|
|
21
|
-
* ```tsx
|
|
22
|
-
* // Will try to place on top first, but will flip if needed
|
|
23
|
-
* <Popper anchorPos="auto-top">...</Popper>
|
|
24
|
-
*
|
|
25
|
-
* // Will try all directions equally
|
|
26
|
-
* <Popper anchorPos="auto">...</Popper>
|
|
27
|
-
* ```
|
|
28
|
-
*/
|
|
29
|
-
export type AutoModifier = 'auto' | 'auto-top' | 'auto-bottom' | 'auto-left' | 'auto-right';
|
|
30
|
-
/**
|
|
31
|
-
* Precise placement modifiers for fine-tuned positioning.
|
|
32
|
-
* These combine a base direction with specific alignment options:
|
|
33
|
-
* - `start`/`end`: Aligns to the beginning or end of the anchor (useful for RTL layouts)
|
|
34
|
-
* - `left`/`right`: Horizontal alignment for vertical placements
|
|
35
|
-
* - `top`/`bottom`: Vertical alignment for horizontal placements
|
|
36
|
-
*
|
|
37
|
-
* @example
|
|
38
|
-
* ```tsx
|
|
39
|
-
* // Corner placements
|
|
40
|
-
* <Popper anchorPos="top-left">Aligns to top-left corner</Popper>
|
|
41
|
-
*
|
|
42
|
-
* // Logical placements (RTL-friendly)
|
|
43
|
-
* <Popper anchorPos="bottom-start">Aligns to bottom edge, start side</Popper>
|
|
44
|
-
*
|
|
45
|
-
* // Side alignments
|
|
46
|
-
* <Popper anchorPos="left-top">Aligns to left side, top edge</Popper>
|
|
47
|
-
* ```
|
|
48
|
-
*/
|
|
49
|
-
export type Modifier = 'top-start' | 'top-end' | 'top-left' | 'top-right' | 'bottom-end' | 'bottom-start' | 'bottom-right' | 'bottom-left' | 'left-top' | 'left-bottom' | 'right-top' | 'right-bottom' | 'bottom-fill' | 'top-fill';
|
|
50
|
-
/**
|
|
51
|
-
* Available placement options for the popper.
|
|
52
|
-
* Combines basic directions, precise modifiers, and auto-placement options
|
|
53
|
-
* to provide full control over popper positioning.
|
|
54
|
-
*
|
|
55
|
-
* Categories:
|
|
56
|
-
* - **Basic directions**: `top`, `bottom`, `left`, `right` - Centered placement
|
|
57
|
-
* - **Corner placements**: `top-left`, `top-right`, `bottom-left`, `bottom-right` - Aligned to corners
|
|
58
|
-
* - **Logical placements**: `top-start`, `top-end`, `bottom-start`, `bottom-end` - RTL-aware alignment
|
|
59
|
-
* - **Side alignments**: `left-top`, `left-bottom`, `right-top`, `right-bottom` - Edge-aligned
|
|
60
|
-
* - **Auto placements**: `auto`, `auto-top`, `auto-bottom`, `auto-left`, `auto-right` - Intelligent positioning
|
|
61
|
-
*
|
|
62
|
-
* @default 'bottom'
|
|
63
|
-
* @example
|
|
64
|
-
* ```tsx
|
|
65
|
-
* // Basic centered placement
|
|
66
|
-
* <Popper anchorPos="bottom">Centered below anchor</Popper>
|
|
67
|
-
*
|
|
68
|
-
* // Corner placement
|
|
69
|
-
* <Popper anchorPos="top-right">Attached to top-right corner</Popper>
|
|
70
|
-
*
|
|
71
|
-
* // Auto placement with priority
|
|
72
|
-
* <Popper anchorPos="auto-left">Try left first, then find best fit</Popper>
|
|
73
|
-
*
|
|
74
|
-
* // RTL-aware placement
|
|
75
|
-
* <Popper anchorPos="top-start">Respects text direction</Popper>
|
|
76
|
-
* ```
|
|
77
|
-
*/
|
|
78
|
-
export type AnchorPos = Direction | Modifier | AutoModifier;
|
|
79
|
-
export interface UsePopperProps {
|
|
80
|
-
readonly anchorElement: HTMLElement | null;
|
|
81
|
-
readonly anchorPos?: AnchorPos;
|
|
82
|
-
readonly positionStrategy?: PositionStrategy;
|
|
83
|
-
readonly autoFlip?: boolean;
|
|
84
|
-
readonly offset?: number;
|
|
85
|
-
readonly viewportMargin?: number;
|
|
86
|
-
readonly isOpen?: boolean;
|
|
87
|
-
}
|
|
88
|
-
export interface UsePopperResult {
|
|
89
|
-
readonly actualPlacement: AnchorPos;
|
|
90
|
-
readonly style: React.CSSProperties | null;
|
|
91
|
-
readonly popperRef: React.MutableRefObject<HTMLDivElement | null>;
|
|
92
|
-
readonly isVisible: boolean;
|
|
93
|
-
readonly calculatePosition: () => void;
|
|
94
|
-
readonly scrollableAncestor: HTMLElement | Window | null;
|
|
95
|
-
readonly setActualPlacement: React.Dispatch<React.SetStateAction<AnchorPos>>;
|
|
96
|
-
readonly setStyle: React.Dispatch<React.SetStateAction<React.CSSProperties | null>>;
|
|
97
|
-
readonly setIsVisible: React.Dispatch<React.SetStateAction<boolean>>;
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Finds the closest scrollable ancestor of an element.
|
|
101
|
-
* A scrollable element is one that has overflow set to auto, scroll, or overlay
|
|
102
|
-
* and has content that overflows, allowing scrolling.
|
|
103
|
-
*
|
|
104
|
-
* @param element - The element to start searching from
|
|
105
|
-
* @param includeHidden - Whether to consider elements with overflow: hidden
|
|
106
|
-
* @returns The closest scrollable ancestor or window if none found
|
|
107
|
-
*/
|
|
108
|
-
export declare const findScrollableAncestor: (element: HTMLElement | null, includeHidden?: boolean) => HTMLElement | Window | null;
|
|
109
|
-
export declare const usePopper: ({ anchorElement, anchorPos, positionStrategy, autoFlip, offset, viewportMargin, isOpen, }: UsePopperProps) => UsePopperResult;
|
|
110
|
-
export default usePopper;
|
package/Popper/usePopprer.js
DELETED
|
@@ -1,505 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.usePopper = exports.findScrollableAncestor = void 0;
|
|
7
|
-
const react_1 = __importDefault(require("react"));
|
|
8
|
-
/**
|
|
9
|
-
* Finds the closest scrollable ancestor of an element.
|
|
10
|
-
* A scrollable element is one that has overflow set to auto, scroll, or overlay
|
|
11
|
-
* and has content that overflows, allowing scrolling.
|
|
12
|
-
*
|
|
13
|
-
* @param element - The element to start searching from
|
|
14
|
-
* @param includeHidden - Whether to consider elements with overflow: hidden
|
|
15
|
-
* @returns The closest scrollable ancestor or window if none found
|
|
16
|
-
*/
|
|
17
|
-
const findScrollableAncestor = (element, includeHidden = false) => {
|
|
18
|
-
if (!element) {
|
|
19
|
-
return null;
|
|
20
|
-
}
|
|
21
|
-
// Helper to check if an element is scrollable
|
|
22
|
-
const isScrollable = (el) => {
|
|
23
|
-
const style = window.getComputedStyle(el);
|
|
24
|
-
const overflow = style.overflow + style.overflowY + style.overflowX;
|
|
25
|
-
// Check if element has overflow that enables scrolling
|
|
26
|
-
const hasOverflow = overflow.includes('auto') ||
|
|
27
|
-
overflow.includes('scroll') ||
|
|
28
|
-
(includeHidden && overflow.includes('hidden'));
|
|
29
|
-
if (!hasOverflow) {
|
|
30
|
-
return false;
|
|
31
|
-
}
|
|
32
|
-
// Check if element actually has scrollable content
|
|
33
|
-
return el.scrollHeight > el.clientHeight || el.scrollWidth > el.clientWidth;
|
|
34
|
-
};
|
|
35
|
-
// Start from parent (skip the element itself)
|
|
36
|
-
let parent = element.parentElement;
|
|
37
|
-
while (parent) {
|
|
38
|
-
if (isScrollable(parent)) {
|
|
39
|
-
return parent;
|
|
40
|
-
}
|
|
41
|
-
parent = parent.parentElement;
|
|
42
|
-
}
|
|
43
|
-
// If no scrollable ancestor found, return window (which is scrollable)
|
|
44
|
-
return window;
|
|
45
|
-
};
|
|
46
|
-
exports.findScrollableAncestor = findScrollableAncestor;
|
|
47
|
-
const usePopper = ({ anchorElement, anchorPos = 'auto', positionStrategy = 'fixed', autoFlip = true, offset = 0, viewportMargin = 10, isOpen = false, }) => {
|
|
48
|
-
const [actualPlacement, setActualPlacement] = react_1.default.useState(anchorPos);
|
|
49
|
-
const [style, setStyle] = react_1.default.useState(null);
|
|
50
|
-
const [isVisible, setIsVisible] = react_1.default.useState(false);
|
|
51
|
-
const popperRef = react_1.default.useRef(null);
|
|
52
|
-
// Finding the nearest scrollable ancestor
|
|
53
|
-
const scrollableAncestor = react_1.default.useMemo(() => {
|
|
54
|
-
if (!anchorElement || typeof window === 'undefined') {
|
|
55
|
-
return null;
|
|
56
|
-
}
|
|
57
|
-
return (0, exports.findScrollableAncestor)(anchorElement);
|
|
58
|
-
}, [anchorElement]);
|
|
59
|
-
// Synchronizing actualPlacement with anchorPos
|
|
60
|
-
react_1.default.useEffect(() => {
|
|
61
|
-
if (actualPlacement !== anchorPos) {
|
|
62
|
-
setActualPlacement(anchorPos);
|
|
63
|
-
}
|
|
64
|
-
}, [actualPlacement, anchorPos]);
|
|
65
|
-
const getPositionStyle = react_1.default.useCallback((props) => {
|
|
66
|
-
const { place, anchorRect, popperRect, forViewportCheck = false } = props;
|
|
67
|
-
const [direction, modifier = ''] = place.split('-');
|
|
68
|
-
let left = anchorRect.left;
|
|
69
|
-
let top = anchorRect.top;
|
|
70
|
-
let width = undefined;
|
|
71
|
-
// Calculating the position relative to the viewport
|
|
72
|
-
switch (direction) {
|
|
73
|
-
case 'top':
|
|
74
|
-
top = anchorRect.top - popperRect.height - offset;
|
|
75
|
-
if (modifier === 'fill') {
|
|
76
|
-
left = anchorRect.left;
|
|
77
|
-
width = anchorRect.width;
|
|
78
|
-
}
|
|
79
|
-
else if (modifier === 'left' || modifier === 'start') {
|
|
80
|
-
left = anchorRect.left;
|
|
81
|
-
}
|
|
82
|
-
else if (modifier === 'right' || modifier === 'end') {
|
|
83
|
-
left = anchorRect.right - popperRect.width;
|
|
84
|
-
}
|
|
85
|
-
else {
|
|
86
|
-
left = anchorRect.left + (anchorRect.width - popperRect.width) / 2;
|
|
87
|
-
}
|
|
88
|
-
break;
|
|
89
|
-
case 'bottom':
|
|
90
|
-
top = anchorRect.bottom + offset;
|
|
91
|
-
if (modifier === 'fill') {
|
|
92
|
-
left = anchorRect.left;
|
|
93
|
-
width = anchorRect.width;
|
|
94
|
-
}
|
|
95
|
-
else if (modifier === 'left' || modifier === 'start') {
|
|
96
|
-
left = anchorRect.left;
|
|
97
|
-
}
|
|
98
|
-
else if (modifier === 'right' || modifier === 'end') {
|
|
99
|
-
left = anchorRect.right - popperRect.width;
|
|
100
|
-
}
|
|
101
|
-
else {
|
|
102
|
-
left = anchorRect.left + (anchorRect.width - popperRect.width) / 2;
|
|
103
|
-
}
|
|
104
|
-
break;
|
|
105
|
-
case 'left':
|
|
106
|
-
left = anchorRect.left - popperRect.width - offset;
|
|
107
|
-
if (modifier === 'top' || modifier === 'start') {
|
|
108
|
-
top = anchorRect.top;
|
|
109
|
-
}
|
|
110
|
-
else if (modifier === 'bottom' || modifier === 'end') {
|
|
111
|
-
top = anchorRect.bottom - popperRect.height;
|
|
112
|
-
}
|
|
113
|
-
else {
|
|
114
|
-
top = anchorRect.top + (anchorRect.height - popperRect.height) / 2;
|
|
115
|
-
}
|
|
116
|
-
break;
|
|
117
|
-
case 'right':
|
|
118
|
-
left = anchorRect.right + offset;
|
|
119
|
-
if (modifier === 'top' || modifier === 'start') {
|
|
120
|
-
top = anchorRect.top;
|
|
121
|
-
}
|
|
122
|
-
else if (modifier === 'bottom' || modifier === 'end') {
|
|
123
|
-
top = anchorRect.bottom - popperRect.height;
|
|
124
|
-
}
|
|
125
|
-
else {
|
|
126
|
-
top = anchorRect.top + (anchorRect.height - popperRect.height) / 2;
|
|
127
|
-
}
|
|
128
|
-
break;
|
|
129
|
-
default:
|
|
130
|
-
left = anchorRect.left + (anchorRect.width - popperRect.width) / 2;
|
|
131
|
-
top = anchorRect.bottom + offset;
|
|
132
|
-
}
|
|
133
|
-
// Returning the viewport coordinates for verification or the final coordinates
|
|
134
|
-
if (forViewportCheck) {
|
|
135
|
-
return { left, top, width };
|
|
136
|
-
}
|
|
137
|
-
// For the final positioning, we take into account the strategy
|
|
138
|
-
if (positionStrategy === 'absolute') {
|
|
139
|
-
return {
|
|
140
|
-
left: left + window.scrollX,
|
|
141
|
-
top: top + window.scrollY,
|
|
142
|
-
width,
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
|
-
return { left, top, width };
|
|
146
|
-
}, [offset, positionStrategy]);
|
|
147
|
-
// const clampPopperToContainer = React.useCallback(
|
|
148
|
-
// (style: { left: number; top: number; width?: number }, _popperRect: DOMRect) => style,
|
|
149
|
-
// [],
|
|
150
|
-
// );
|
|
151
|
-
const clampPopperToContainer = react_1.default.useCallback((style, popperRect) => {
|
|
152
|
-
// Если нет scrollableAncestor, используем document.documentElement как fallback
|
|
153
|
-
const container = scrollableAncestor instanceof HTMLElement ? scrollableAncestor : document.documentElement;
|
|
154
|
-
const containerRect = container.getBoundingClientRect();
|
|
155
|
-
// Базовые границы контейнера с учетом отступа
|
|
156
|
-
let minLeft = containerRect.left + viewportMargin;
|
|
157
|
-
let maxLeft = containerRect.right - popperRect.width - viewportMargin;
|
|
158
|
-
let minTop = containerRect.top + viewportMargin;
|
|
159
|
-
let maxTop = containerRect.bottom - popperRect.height - viewportMargin;
|
|
160
|
-
// Для fixed позиционирования добавляем ограничения viewport
|
|
161
|
-
if (positionStrategy === 'fixed') {
|
|
162
|
-
// Границы viewport с учетом отступа
|
|
163
|
-
const viewportMinLeft = viewportMargin;
|
|
164
|
-
const viewportMaxLeft = window.innerWidth - popperRect.width - viewportMargin;
|
|
165
|
-
const viewportMinTop = viewportMargin;
|
|
166
|
-
const viewportMaxTop = window.innerHeight - popperRect.height - viewportMargin;
|
|
167
|
-
// Берем пересечение границ контейнера и viewport
|
|
168
|
-
minLeft = Math.max(minLeft, viewportMinLeft);
|
|
169
|
-
maxLeft = Math.min(maxLeft, viewportMaxLeft);
|
|
170
|
-
minTop = Math.max(minTop, viewportMinTop);
|
|
171
|
-
maxTop = Math.min(maxTop, viewportMaxTop);
|
|
172
|
-
}
|
|
173
|
-
// Убеждаемся, что границы валидны (min не больше max)
|
|
174
|
-
const validMinLeft = Math.min(minLeft, maxLeft);
|
|
175
|
-
const validMaxLeft = Math.max(minLeft, maxLeft);
|
|
176
|
-
const validMinTop = Math.min(minTop, maxTop);
|
|
177
|
-
const validMaxTop = Math.max(minTop, maxTop);
|
|
178
|
-
// Ограничиваем позицию
|
|
179
|
-
const clampedLeft = Math.max(validMinLeft, Math.min(style.left, validMaxLeft));
|
|
180
|
-
const clampedTop = Math.max(validMinTop, Math.min(style.top, validMaxTop));
|
|
181
|
-
return {
|
|
182
|
-
left: clampedLeft,
|
|
183
|
-
top: clampedTop,
|
|
184
|
-
width: style.width,
|
|
185
|
-
};
|
|
186
|
-
}, [positionStrategy, scrollableAncestor, viewportMargin]);
|
|
187
|
-
const checkIfViewportFits = react_1.default.useCallback((style, popperRect) => {
|
|
188
|
-
const left = style.left;
|
|
189
|
-
const top = style.top;
|
|
190
|
-
const right = left + popperRect.width;
|
|
191
|
-
const bottom = top + popperRect.height;
|
|
192
|
-
if (positionStrategy === 'absolute' && scrollableAncestor instanceof HTMLElement) {
|
|
193
|
-
const containerRect = scrollableAncestor.getBoundingClientRect();
|
|
194
|
-
const relativeLeft = left - containerRect.left;
|
|
195
|
-
const relativeTop = top - containerRect.top;
|
|
196
|
-
const relativeRight = relativeLeft + popperRect.width;
|
|
197
|
-
const relativeBottom = relativeTop + popperRect.height;
|
|
198
|
-
const isWithinHorizontal = relativeLeft >= viewportMargin && relativeRight <= containerRect.width - viewportMargin;
|
|
199
|
-
const isWithinVertical = relativeTop >= viewportMargin && relativeBottom <= containerRect.height - viewportMargin;
|
|
200
|
-
return isWithinHorizontal && isWithinVertical;
|
|
201
|
-
}
|
|
202
|
-
const viewportWidth = window.innerWidth;
|
|
203
|
-
const viewportHeight = window.innerHeight;
|
|
204
|
-
const isWithinHorizontal = left >= viewportMargin && right <= viewportWidth - viewportMargin;
|
|
205
|
-
const isWithinVertical = top >= viewportMargin && bottom <= viewportHeight - viewportMargin;
|
|
206
|
-
const hasValidPosition = left >= 0 && top >= 0;
|
|
207
|
-
return hasValidPosition && isWithinHorizontal && isWithinVertical;
|
|
208
|
-
}, [viewportMargin, scrollableAncestor, positionStrategy]);
|
|
209
|
-
const placementsOrder = react_1.default.useMemo(() => {
|
|
210
|
-
const basePlacements = {
|
|
211
|
-
top: ['top', 'top-left', 'top-right', 'top-start', 'top-end'],
|
|
212
|
-
bottom: ['bottom', 'bottom-left', 'bottom-right', 'bottom-start', 'bottom-end'],
|
|
213
|
-
left: ['left', 'left-top', 'left-bottom'],
|
|
214
|
-
right: ['right', 'right-top', 'right-bottom'],
|
|
215
|
-
};
|
|
216
|
-
const allPlacements = [
|
|
217
|
-
...basePlacements.top,
|
|
218
|
-
...basePlacements.bottom,
|
|
219
|
-
...basePlacements.left,
|
|
220
|
-
...basePlacements.right,
|
|
221
|
-
];
|
|
222
|
-
const order = {};
|
|
223
|
-
allPlacements.forEach(placement => {
|
|
224
|
-
const [direction] = placement.split('-');
|
|
225
|
-
// Priority: same direction > opposite > the rest
|
|
226
|
-
const opposite = direction === 'top'
|
|
227
|
-
? 'bottom'
|
|
228
|
-
: direction === 'bottom'
|
|
229
|
-
? 'top'
|
|
230
|
-
: direction === 'left'
|
|
231
|
-
? 'right'
|
|
232
|
-
: 'left';
|
|
233
|
-
order[placement] = [
|
|
234
|
-
placement,
|
|
235
|
-
...basePlacements[direction].filter(p => p !== placement),
|
|
236
|
-
...(basePlacements[opposite] || []),
|
|
237
|
-
...(direction !== 'left' && direction !== 'right' ? basePlacements.left : []),
|
|
238
|
-
...(direction !== 'left' && direction !== 'right' ? basePlacements.right : []),
|
|
239
|
-
];
|
|
240
|
-
});
|
|
241
|
-
// console.log(order);
|
|
242
|
-
return order;
|
|
243
|
-
}, []);
|
|
244
|
-
const getPreferredPlacements = react_1.default.useCallback((preferredPlacement, anchorRect, popperRect) => {
|
|
245
|
-
// Check the auto placements
|
|
246
|
-
if (preferredPlacement.startsWith('auto')) {
|
|
247
|
-
const [, preferredDirection = 'bottom'] = preferredPlacement.split('-');
|
|
248
|
-
const allPlacements = [
|
|
249
|
-
'bottom',
|
|
250
|
-
'bottom-start',
|
|
251
|
-
'bottom-end',
|
|
252
|
-
'bottom-left',
|
|
253
|
-
'bottom-right',
|
|
254
|
-
'top',
|
|
255
|
-
'top-left',
|
|
256
|
-
'top-right',
|
|
257
|
-
'top-start',
|
|
258
|
-
'top-end',
|
|
259
|
-
'left',
|
|
260
|
-
'left-top',
|
|
261
|
-
'left-bottom',
|
|
262
|
-
'right',
|
|
263
|
-
'right-top',
|
|
264
|
-
'right-bottom',
|
|
265
|
-
];
|
|
266
|
-
// Sorting placements
|
|
267
|
-
const sortedPlacements = [...allPlacements].sort((a, b) => {
|
|
268
|
-
const aDir = a.split('-')[0];
|
|
269
|
-
const bDir = b.split('-')[0];
|
|
270
|
-
if (aDir === preferredDirection && bDir !== preferredDirection)
|
|
271
|
-
return -1;
|
|
272
|
-
if (aDir !== preferredDirection && bDir === preferredDirection)
|
|
273
|
-
return 1;
|
|
274
|
-
return 0;
|
|
275
|
-
});
|
|
276
|
-
for (const place of sortedPlacements) {
|
|
277
|
-
const viewportStyle = getPositionStyle({
|
|
278
|
-
place,
|
|
279
|
-
anchorRect,
|
|
280
|
-
popperRect,
|
|
281
|
-
forViewportCheck: true,
|
|
282
|
-
});
|
|
283
|
-
const fits = checkIfViewportFits(viewportStyle, popperRect);
|
|
284
|
-
if (fits) {
|
|
285
|
-
const finalStyle = getPositionStyle({
|
|
286
|
-
place,
|
|
287
|
-
anchorRect,
|
|
288
|
-
popperRect,
|
|
289
|
-
forViewportCheck: false,
|
|
290
|
-
});
|
|
291
|
-
return {
|
|
292
|
-
found: true,
|
|
293
|
-
placement: place,
|
|
294
|
-
style: clampPopperToContainer(finalStyle, popperRect),
|
|
295
|
-
};
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
if (!autoFlip) {
|
|
300
|
-
const finalStyle = getPositionStyle({
|
|
301
|
-
place: preferredPlacement,
|
|
302
|
-
anchorRect,
|
|
303
|
-
popperRect,
|
|
304
|
-
forViewportCheck: false,
|
|
305
|
-
});
|
|
306
|
-
return {
|
|
307
|
-
found: false,
|
|
308
|
-
placement: preferredPlacement,
|
|
309
|
-
style: clampPopperToContainer(finalStyle, popperRect),
|
|
310
|
-
};
|
|
311
|
-
}
|
|
312
|
-
/**
|
|
313
|
-
* bottom-fill, top-fill
|
|
314
|
-
*/
|
|
315
|
-
if (preferredPlacement.endsWith('fill')) {
|
|
316
|
-
const [preferredDirection = 'bottom'] = preferredPlacement.split('-');
|
|
317
|
-
const allPlacements = ['top-fill', 'bottom-fill'];
|
|
318
|
-
const sortedPlacements = [...allPlacements].sort((a, b) => {
|
|
319
|
-
const aDir = a.split('-')[0];
|
|
320
|
-
const bDir = b.split('-')[0];
|
|
321
|
-
if (aDir === preferredDirection && bDir !== preferredDirection)
|
|
322
|
-
return -1;
|
|
323
|
-
if (aDir !== preferredDirection && bDir === preferredDirection)
|
|
324
|
-
return 1;
|
|
325
|
-
return 0;
|
|
326
|
-
});
|
|
327
|
-
for (const place of sortedPlacements) {
|
|
328
|
-
const viewportStyle = getPositionStyle({
|
|
329
|
-
place,
|
|
330
|
-
anchorRect,
|
|
331
|
-
popperRect,
|
|
332
|
-
forViewportCheck: true,
|
|
333
|
-
});
|
|
334
|
-
const fits = checkIfViewportFits(viewportStyle, popperRect);
|
|
335
|
-
if (fits) {
|
|
336
|
-
const finalStyle = getPositionStyle({
|
|
337
|
-
place,
|
|
338
|
-
anchorRect,
|
|
339
|
-
popperRect,
|
|
340
|
-
forViewportCheck: false,
|
|
341
|
-
});
|
|
342
|
-
return {
|
|
343
|
-
found: true,
|
|
344
|
-
placement: place,
|
|
345
|
-
style: clampPopperToContainer(finalStyle, popperRect),
|
|
346
|
-
};
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
/**
|
|
351
|
-
* Other
|
|
352
|
-
*/
|
|
353
|
-
const order = placementsOrder[preferredPlacement] || placementsOrder.bottom;
|
|
354
|
-
for (const place of order) {
|
|
355
|
-
const viewportStyle = getPositionStyle({
|
|
356
|
-
place,
|
|
357
|
-
anchorRect,
|
|
358
|
-
popperRect,
|
|
359
|
-
forViewportCheck: true,
|
|
360
|
-
});
|
|
361
|
-
const fits = checkIfViewportFits(viewportStyle, popperRect);
|
|
362
|
-
if (fits) {
|
|
363
|
-
const finalStyle = getPositionStyle({
|
|
364
|
-
place,
|
|
365
|
-
anchorRect,
|
|
366
|
-
popperRect,
|
|
367
|
-
forViewportCheck: false,
|
|
368
|
-
});
|
|
369
|
-
return {
|
|
370
|
-
found: true,
|
|
371
|
-
placement: place,
|
|
372
|
-
style: clampPopperToContainer(finalStyle, popperRect),
|
|
373
|
-
};
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
const finalStyle = getPositionStyle({
|
|
377
|
-
place: preferredPlacement,
|
|
378
|
-
anchorRect,
|
|
379
|
-
popperRect,
|
|
380
|
-
forViewportCheck: false,
|
|
381
|
-
});
|
|
382
|
-
return {
|
|
383
|
-
found: false,
|
|
384
|
-
placement: preferredPlacement,
|
|
385
|
-
style: clampPopperToContainer(finalStyle, popperRect),
|
|
386
|
-
};
|
|
387
|
-
}, [autoFlip, getPositionStyle, checkIfViewportFits, clampPopperToContainer, placementsOrder]);
|
|
388
|
-
const calculatePosition = react_1.default.useCallback(() => {
|
|
389
|
-
if (!anchorElement || !popperRef.current) {
|
|
390
|
-
return;
|
|
391
|
-
}
|
|
392
|
-
const anchorRect = anchorElement.getBoundingClientRect();
|
|
393
|
-
const popperRect = popperRef.current.getBoundingClientRect();
|
|
394
|
-
const { style, placement, found } = getPreferredPlacements(anchorPos, anchorRect, popperRect);
|
|
395
|
-
if (found) {
|
|
396
|
-
setActualPlacement(placement);
|
|
397
|
-
}
|
|
398
|
-
setStyle(style);
|
|
399
|
-
}, [anchorElement, anchorPos, getPreferredPlacements]);
|
|
400
|
-
// const getTransformOrigin = React.useCallback((placement: AnchorPos): string => {
|
|
401
|
-
// if (placement.startsWith('top')) return 'bottom center';
|
|
402
|
-
// if (placement.startsWith('bottom')) return 'top center';
|
|
403
|
-
// if (placement.startsWith('left')) return 'right center';
|
|
404
|
-
// if (placement.startsWith('right')) return 'left center';
|
|
405
|
-
//
|
|
406
|
-
// return 'top center';
|
|
407
|
-
// }, []);
|
|
408
|
-
/**
|
|
409
|
-
* Open / Close popper logic
|
|
410
|
-
*/
|
|
411
|
-
react_1.default.useEffect(() => {
|
|
412
|
-
if (!isOpen) {
|
|
413
|
-
setIsVisible(false);
|
|
414
|
-
setStyle(null);
|
|
415
|
-
}
|
|
416
|
-
else if (anchorElement && isOpen && popperRef.current) {
|
|
417
|
-
calculatePosition();
|
|
418
|
-
setIsVisible(true);
|
|
419
|
-
}
|
|
420
|
-
}, [actualPlacement, anchorElement, getPreferredPlacements, isOpen, calculatePosition]);
|
|
421
|
-
/**
|
|
422
|
-
* The anchor element changes
|
|
423
|
-
*/
|
|
424
|
-
react_1.default.useEffect(() => {
|
|
425
|
-
if (!isOpen || !anchorElement) {
|
|
426
|
-
return;
|
|
427
|
-
}
|
|
428
|
-
const observer = new MutationObserver(() => {
|
|
429
|
-
window.requestAnimationFrame(() => {
|
|
430
|
-
// console.log('The anchor element was change');
|
|
431
|
-
calculatePosition();
|
|
432
|
-
});
|
|
433
|
-
});
|
|
434
|
-
observer.observe(anchorElement, {
|
|
435
|
-
attributes: true,
|
|
436
|
-
childList: true,
|
|
437
|
-
subtree: true,
|
|
438
|
-
});
|
|
439
|
-
// eslint-disable-next-line consistent-return
|
|
440
|
-
return () => {
|
|
441
|
-
observer.disconnect();
|
|
442
|
-
};
|
|
443
|
-
}, [isOpen, anchorElement, calculatePosition]);
|
|
444
|
-
/**
|
|
445
|
-
* On scroll - recalculate position
|
|
446
|
-
*/
|
|
447
|
-
react_1.default.useEffect(() => {
|
|
448
|
-
if (!isOpen || !scrollableAncestor) {
|
|
449
|
-
return;
|
|
450
|
-
}
|
|
451
|
-
const handleScroll = () => {
|
|
452
|
-
window.requestAnimationFrame(() => {
|
|
453
|
-
calculatePosition();
|
|
454
|
-
});
|
|
455
|
-
};
|
|
456
|
-
// parent scroll listener
|
|
457
|
-
if (scrollableAncestor instanceof HTMLElement) {
|
|
458
|
-
scrollableAncestor.addEventListener('scroll', handleScroll, { passive: true });
|
|
459
|
-
}
|
|
460
|
-
else if (scrollableAncestor === window) {
|
|
461
|
-
window.addEventListener('scroll', handleScroll, { passive: true });
|
|
462
|
-
}
|
|
463
|
-
// eslint-disable-next-line consistent-return
|
|
464
|
-
return () => {
|
|
465
|
-
if (scrollableAncestor instanceof HTMLElement) {
|
|
466
|
-
scrollableAncestor.removeEventListener('scroll', handleScroll);
|
|
467
|
-
}
|
|
468
|
-
else if (scrollableAncestor === window) {
|
|
469
|
-
window.removeEventListener('scroll', handleScroll);
|
|
470
|
-
}
|
|
471
|
-
};
|
|
472
|
-
}, [isOpen, scrollableAncestor, calculatePosition]);
|
|
473
|
-
/**
|
|
474
|
-
* On window resize - recalculate position
|
|
475
|
-
*/
|
|
476
|
-
react_1.default.useEffect(() => {
|
|
477
|
-
if (!isOpen) {
|
|
478
|
-
return;
|
|
479
|
-
}
|
|
480
|
-
const handleResize = () => {
|
|
481
|
-
window.requestAnimationFrame(() => {
|
|
482
|
-
calculatePosition();
|
|
483
|
-
});
|
|
484
|
-
};
|
|
485
|
-
// parent scroll listener
|
|
486
|
-
window.addEventListener('resize', handleResize);
|
|
487
|
-
// eslint-disable-next-line consistent-return
|
|
488
|
-
return () => {
|
|
489
|
-
window.removeEventListener('resize', handleResize);
|
|
490
|
-
};
|
|
491
|
-
}, [calculatePosition, isOpen]);
|
|
492
|
-
return {
|
|
493
|
-
actualPlacement,
|
|
494
|
-
style,
|
|
495
|
-
popperRef,
|
|
496
|
-
isVisible,
|
|
497
|
-
scrollableAncestor,
|
|
498
|
-
calculatePosition,
|
|
499
|
-
setActualPlacement,
|
|
500
|
-
setStyle,
|
|
501
|
-
setIsVisible,
|
|
502
|
-
};
|
|
503
|
-
};
|
|
504
|
-
exports.usePopper = usePopper;
|
|
505
|
-
exports.default = exports.usePopper;
|