@patternfly/patternfly-doc-core 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.astro/collections/textContent.schema.json +6 -0
- package/README.md +11 -10
- package/astro.config.mjs +8 -1
- package/cli/buildPropsData.ts +113 -0
- package/cli/cli.ts +52 -6
- package/cli/getConfig.ts +6 -0
- package/cli/hasFile.ts +5 -0
- package/cli/templates/pf-docs.config.mjs +13 -2
- package/cli/tsDocGen.js +199 -0
- package/dist/cli/buildPropsData.js +68 -0
- package/dist/cli/cli.js +37 -4
- package/dist/cli/hasFile.js +4 -0
- package/dist/cli/templates/pf-docs.config.mjs +12 -1
- package/dist/cli/tsDocGen.js +153 -0
- package/dist/cli/tsconfig.tsbuildinfo +1 -1
- package/dist/client/_astro/_page_.SnUmZn2y.css +1 -0
- package/dist/client/design-foundations/typography/index.html +219 -0
- package/dist/client/design-foundations/usage-and-behavior/index.html +368 -0
- package/dist/client/get-started/contribute/index.html +115 -0
- package/dist/client/index.html +42 -0
- package/dist/server/_@astrojs-ssr-adapter.mjs +1 -0
- package/dist/server/_noop-middleware.mjs +3 -0
- package/dist/server/chunks/PropsTables_D_v4KAMn.mjs +1826 -0
- package/dist/server/chunks/_@astrojs-ssr-adapter_ByVMUK8O.mjs +3621 -0
- package/dist/server/chunks/_astro_assets_CLOMnm-3.mjs +1507 -0
- package/dist/server/chunks/_astro_data-layer-content_DDGBHvtb.mjs +1 -0
- package/dist/server/chunks/angle-down-icon_BNJvzYv-.mjs +3970 -0
- package/dist/server/chunks/astro/server_D4f31GMD.mjs +2769 -0
- package/dist/server/chunks/astro-designed-error-pages_CpHpbfhr.mjs +282 -0
- package/dist/server/chunks/consts_BmVDRGlB.mjs +32 -0
- package/dist/server/chunks/content-assets_DleWbedO.mjs +1 -0
- package/dist/server/chunks/content-modules_Dz-S_Wwv.mjs +1 -0
- package/dist/server/chunks/path_Cvt6sEOY.mjs +58 -0
- package/dist/server/chunks/sharp_BYpUyJGL.mjs +88 -0
- package/dist/server/entry.mjs +45 -0
- package/dist/server/manifest_Bln0Ib60.mjs +102 -0
- package/dist/server/pages/_image.astro.mjs +132 -0
- package/dist/server/pages/_section_/_---page_.astro.mjs +1 -0
- package/dist/server/pages/_section_/_page_/_---tab_.astro.mjs +1 -0
- package/dist/server/pages/index.astro.mjs +1 -0
- package/dist/server/pages/props.astro.mjs +25 -0
- package/dist/server/renderers.mjs +259 -0
- package/jest.config.ts +1 -1
- package/package.json +5 -2
- package/pf-docs.config.mjs +31 -0
- package/release.config.mjs +1 -1
- package/src/components/PropsTable.tsx +3 -3
- package/src/components/PropsTables.astro +38 -0
- package/src/content.config.ts +1 -0
- package/src/pages/[section]/[...page].astro +16 -8
- package/src/pages/[section]/[page]/[...tab].astro +4 -1
- package/src/pages/props.ts +17 -0
- package/textContent/contribute.md +1 -0
- package/dist/design-foundations/typography/index.html +0 -193
- package/dist/design-foundations/usage-and-behavior/index.html +0 -342
- package/dist/get-started/contribute/index.html +0 -89
- package/dist/index.html +0 -42
- /package/dist/{PF-HorizontalLogo-Color.svg → client/PF-HorizontalLogo-Color.svg} +0 -0
- /package/dist/{PF-HorizontalLogo-Reverse.svg → client/PF-HorizontalLogo-Reverse.svg} +0 -0
- /package/dist/{_astro → client/_astro}/Button.C3_jB5tC.js +0 -0
- /package/dist/{_astro → client/_astro}/ClientRouter.astro_astro_type_script_index_0_lang.Cainpjm5.js +0 -0
- /package/dist/{_astro → client/_astro}/Navigation.Cede__Ud.js +0 -0
- /package/dist/{_astro → client/_astro}/PageContext.C7BqCh9N.js +0 -0
- /package/dist/{_astro → client/_astro}/PageToggle.DDEjruql.js +0 -0
- /package/dist/{_astro → client/_astro}/RedHatDisplayVF-Italic.CRpusWc8.woff2 +0 -0
- /package/dist/{_astro → client/_astro}/RedHatDisplayVF.CYDHf1NI.woff2 +0 -0
- /package/dist/{_astro → client/_astro}/RedHatMonoVF-Italic.DGQo2ogW.woff2 +0 -0
- /package/dist/{_astro → client/_astro}/RedHatMonoVF.C4fMH6Vz.woff2 +0 -0
- /package/dist/{_astro → client/_astro}/RedHatTextVF-Italic.Dkj_WqbA.woff2 +0 -0
- /package/dist/{_astro → client/_astro}/RedHatTextVF.wYvZ7prR.woff2 +0 -0
- /package/dist/{_astro → client/_astro}/Toolbar.TAdHxLSQ.js +0 -0
- /package/dist/{_astro → client/_astro}/_page_.CXyz_BEo.css +0 -0
- /package/dist/{_astro → client/_astro}/_page_.DVvr_Mfl.css +0 -0
- /package/dist/{_astro → client/_astro}/client.CeeiqVaE.js +0 -0
- /package/dist/{_astro → client/_astro}/divider.BSD-oFoh.js +0 -0
- /package/dist/{_astro → client/_astro}/fa-solid-900.DguXoeIz.woff2 +0 -0
- /package/dist/{_astro → client/_astro}/index.CTH3fVMn.js +0 -0
- /package/dist/{_astro → client/_astro}/page.B65lVdBS.js +0 -0
- /package/dist/{_astro → client/_astro}/pf-v6-pficon.Dy6oiu9u.woff2 +0 -0
- /package/dist/{avatarImg.svg → client/avatarImg.svg} +0 -0
- /package/dist/{avatarImgDark.svg → client/avatarImgDark.svg} +0 -0
- /package/dist/{content → client/content}/typography/line-height.png +0 -0
- /package/dist/{favicon.svg → client/favicon.svg} +0 -0
|
@@ -0,0 +1,3970 @@
|
|
|
1
|
+
import { __rest } from 'tslib';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import React__default, { useMemo } from 'react';
|
|
4
|
+
/* empty css */
|
|
5
|
+
import * as ReactDOM from 'react-dom';
|
|
6
|
+
|
|
7
|
+
/** Joins args into a className string
|
|
8
|
+
*
|
|
9
|
+
* @param {any} args list of objects, string, or arrays to reduce
|
|
10
|
+
*/
|
|
11
|
+
function css(...args) {
|
|
12
|
+
// Adapted from https://github.com/JedWatson/classnames/blob/master/index.js
|
|
13
|
+
const classes = [];
|
|
14
|
+
const hasOwn = {}.hasOwnProperty;
|
|
15
|
+
args.filter(Boolean).forEach((arg) => {
|
|
16
|
+
const argType = typeof arg;
|
|
17
|
+
if (argType === 'string' || argType === 'number') {
|
|
18
|
+
classes.push(arg);
|
|
19
|
+
}
|
|
20
|
+
else if (Array.isArray(arg) && arg.length) {
|
|
21
|
+
const inner = css(...arg);
|
|
22
|
+
if (inner) {
|
|
23
|
+
classes.push(inner);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
else if (argType === 'object') {
|
|
27
|
+
for (const key in arg) {
|
|
28
|
+
if (hasOwn.call(arg, key) && arg[key]) {
|
|
29
|
+
classes.push(key);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
return classes.join(' ');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const t_global_breakpoint_sm = {
|
|
38
|
+
"value": "36rem"};
|
|
39
|
+
|
|
40
|
+
const t_global_breakpoint_md = {
|
|
41
|
+
"value": "48rem"};
|
|
42
|
+
|
|
43
|
+
const t_global_breakpoint_lg = {
|
|
44
|
+
"value": "62rem"};
|
|
45
|
+
|
|
46
|
+
const t_global_breakpoint_xl = {
|
|
47
|
+
"value": "75rem"};
|
|
48
|
+
|
|
49
|
+
const t_global_breakpoint_2xl = {
|
|
50
|
+
"value": "90.625rem"};
|
|
51
|
+
|
|
52
|
+
const t_global_breakpoint_height_sm = {
|
|
53
|
+
"value": "0rem"};
|
|
54
|
+
|
|
55
|
+
const t_global_breakpoint_height_md = {
|
|
56
|
+
"value": "40rem"};
|
|
57
|
+
|
|
58
|
+
const t_global_breakpoint_height_lg = {
|
|
59
|
+
"value": "48rem"};
|
|
60
|
+
|
|
61
|
+
const t_global_breakpoint_height_xl = {
|
|
62
|
+
"value": "60rem"};
|
|
63
|
+
|
|
64
|
+
const t_global_breakpoint_height_2xl = {
|
|
65
|
+
"value": "80rem"};
|
|
66
|
+
|
|
67
|
+
let currentId$1 = 0;
|
|
68
|
+
/**
|
|
69
|
+
* Factory to create Icon class components for consumers
|
|
70
|
+
*/
|
|
71
|
+
function createIcon({ name, xOffset = 0, yOffset = 0, width, height, svgPath }) {
|
|
72
|
+
var _a;
|
|
73
|
+
return _a = class SVGIcon extends React.Component {
|
|
74
|
+
constructor() {
|
|
75
|
+
super(...arguments);
|
|
76
|
+
this.id = `icon-title-${currentId$1++}`;
|
|
77
|
+
}
|
|
78
|
+
render() {
|
|
79
|
+
const _b = this.props, { title, className } = _b, props = __rest(_b, ["title", "className"]);
|
|
80
|
+
const classes = className ? `pf-v6-svg ${className}` : 'pf-v6-svg';
|
|
81
|
+
const hasTitle = Boolean(title);
|
|
82
|
+
const viewBox = [xOffset, yOffset, width, height].join(' ');
|
|
83
|
+
return (React.createElement("svg", Object.assign({ className: classes, viewBox: viewBox, fill: "currentColor", "aria-labelledby": hasTitle ? this.id : null, "aria-hidden": hasTitle ? null : true, role: "img", width: "1em", height: "1em" }, props),
|
|
84
|
+
hasTitle && React.createElement("title", { id: this.id }, title),
|
|
85
|
+
React.createElement("path", { d: svgPath })));
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
_a.displayName = name,
|
|
89
|
+
_a;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const CheckCircleIconConfig = {
|
|
93
|
+
name: 'CheckCircleIcon',
|
|
94
|
+
height: 512,
|
|
95
|
+
width: 512,
|
|
96
|
+
svgPath: 'M504 256c0 136.967-111.033 248-248 248S8 392.967 8 256 119.033 8 256 8s248 111.033 248 248zM227.314 387.314l184-184c6.248-6.248 6.248-16.379 0-22.627l-22.627-22.627c-6.248-6.249-16.379-6.249-22.628 0L216 308.118l-70.059-70.059c-6.248-6.248-16.379-6.248-22.628 0l-22.627 22.627c-6.248 6.248-6.248 16.379 0 22.627l104 104c6.249 6.249 16.379 6.249 22.628.001z',
|
|
97
|
+
yOffset: 0,
|
|
98
|
+
xOffset: 0,
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const CheckCircleIcon = createIcon(CheckCircleIconConfig);
|
|
102
|
+
|
|
103
|
+
const ExclamationCircleIconConfig = {
|
|
104
|
+
name: 'ExclamationCircleIcon',
|
|
105
|
+
height: 512,
|
|
106
|
+
width: 512,
|
|
107
|
+
svgPath: 'M504 256c0 136.997-111.043 248-248 248S8 392.997 8 256C8 119.083 119.043 8 256 8s248 111.083 248 248zm-248 50c-25.405 0-46 20.595-46 46s20.595 46 46 46 46-20.595 46-46-20.595-46-46-46zm-43.673-165.346l7.418 136c.347 6.364 5.609 11.346 11.982 11.346h48.546c6.373 0 11.635-4.982 11.982-11.346l7.418-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884 0-12.356 5.78-11.981 12.654z',
|
|
108
|
+
yOffset: 0,
|
|
109
|
+
xOffset: 0,
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const ExclamationCircleIcon = createIcon(ExclamationCircleIconConfig);
|
|
113
|
+
|
|
114
|
+
const ExclamationTriangleIconConfig = {
|
|
115
|
+
name: 'ExclamationTriangleIcon',
|
|
116
|
+
height: 512,
|
|
117
|
+
width: 576,
|
|
118
|
+
svgPath: 'M569.517 440.013C587.975 472.007 564.806 512 527.94 512H48.054c-36.937 0-59.999-40.055-41.577-71.987L246.423 23.985c18.467-32.009 64.72-31.951 83.154 0l239.94 416.028zM288 354c-25.405 0-46 20.595-46 46s20.595 46 46 46 46-20.595 46-46-20.595-46-46-46zm-43.673-165.346l7.418 136c.347 6.364 5.609 11.346 11.982 11.346h48.546c6.373 0 11.635-4.982 11.982-11.346l7.418-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884 0-12.356 5.78-11.981 12.654z',
|
|
119
|
+
yOffset: 0,
|
|
120
|
+
xOffset: 0,
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
const ExclamationTriangleIcon = createIcon(ExclamationTriangleIconConfig);
|
|
124
|
+
|
|
125
|
+
const InfoCircleIconConfig = {
|
|
126
|
+
name: 'InfoCircleIcon',
|
|
127
|
+
height: 512,
|
|
128
|
+
width: 512,
|
|
129
|
+
svgPath: 'M256 8C119.043 8 8 119.083 8 256c0 136.997 111.043 248 248 248s248-111.003 248-248C504 119.083 392.957 8 256 8zm0 110c23.196 0 42 18.804 42 42s-18.804 42-42 42-42-18.804-42-42 18.804-42 42-42zm56 254c0 6.627-5.373 12-12 12h-88c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h12v-64h-12c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h64c6.627 0 12 5.373 12 12v100h12c6.627 0 12 5.373 12 12v24z',
|
|
130
|
+
yOffset: 0,
|
|
131
|
+
xOffset: 0,
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const InfoCircleIcon = createIcon(InfoCircleIconConfig);
|
|
135
|
+
|
|
136
|
+
const BellIconConfig = {
|
|
137
|
+
name: 'BellIcon',
|
|
138
|
+
height: 1024,
|
|
139
|
+
width: 896,
|
|
140
|
+
svgPath: 'M448,0 C465.333333,0 480.333333,6.33333333 493,19 C505.666667,31.6666667 512,46.6666667 512,64 L512,106 L514.23,106.45 C587.89,121.39 648.48,157.24 696,214 C744,271.333333 768,338.666667 768,416 C768,500 780,568.666667 804,622 C818.666667,652.666667 841.333333,684 872,716 C873.773676,718.829136 875.780658,721.505113 878,724 C890,737.333333 896,752.333333 896,769 C896,785.666667 890,800.333333 878,813 C866,825.666667 850.666667,832 832,832 L63.3,832 C44.9533333,831.84 29.8533333,825.506667 18,813 C6,800.333333 0,785.666667 0,769 C0,752.333333 6,737.333333 18,724 L24,716 L25.06,714.9 C55.1933333,683.28 77.5066667,652.313333 92,622 C116,568.666667 128,500 128,416 C128,338.666667 152,271.333333 200,214 C248,156.666667 309.333333,120.666667 384,106 L384,63.31 C384.166667,46.27 390.5,31.5 403,19 C415.666667,6.33333333 430.666667,0 448,0 Z M576,896 L576,897.08 C575.74,932.6 563.073333,962.573333 538,987 C512.666667,1011.66667 482.666667,1024 448,1024 C413.333333,1024 383.333333,1011.66667 358,987 C332.666667,962.333333 320,932 320,896 L576,896 Z',
|
|
141
|
+
yOffset: 0,
|
|
142
|
+
xOffset: 0,
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
const BellIcon = createIcon(BellIconConfig);
|
|
146
|
+
|
|
147
|
+
var ValidatedOptions;
|
|
148
|
+
(function (ValidatedOptions) {
|
|
149
|
+
ValidatedOptions["success"] = "success";
|
|
150
|
+
ValidatedOptions["error"] = "error";
|
|
151
|
+
ValidatedOptions["warning"] = "warning";
|
|
152
|
+
ValidatedOptions["default"] = "default";
|
|
153
|
+
})(ValidatedOptions || (ValidatedOptions = {}));
|
|
154
|
+
const KeyTypes = {
|
|
155
|
+
Space: ' ',
|
|
156
|
+
Escape: 'Escape',
|
|
157
|
+
Enter: 'Enter'};
|
|
158
|
+
const globalWidthBreakpoints = {
|
|
159
|
+
sm: parseInt(t_global_breakpoint_sm.value) * 16,
|
|
160
|
+
md: parseInt(t_global_breakpoint_md.value) * 16,
|
|
161
|
+
lg: parseInt(t_global_breakpoint_lg.value) * 16,
|
|
162
|
+
xl: parseInt(t_global_breakpoint_xl.value) * 16,
|
|
163
|
+
'2xl': parseInt(t_global_breakpoint_2xl.value) * 16
|
|
164
|
+
};
|
|
165
|
+
const globalHeightBreakpoints = {
|
|
166
|
+
sm: parseInt(t_global_breakpoint_height_sm.value) * 16,
|
|
167
|
+
md: parseInt(t_global_breakpoint_height_md.value) * 16,
|
|
168
|
+
lg: parseInt(t_global_breakpoint_height_lg.value) * 16,
|
|
169
|
+
xl: parseInt(t_global_breakpoint_height_xl.value) * 16,
|
|
170
|
+
'2xl': parseInt(t_global_breakpoint_height_2xl.value) * 16
|
|
171
|
+
};
|
|
172
|
+
const statusIcons = {
|
|
173
|
+
success: CheckCircleIcon,
|
|
174
|
+
danger: ExclamationCircleIcon,
|
|
175
|
+
warning: ExclamationTriangleIcon,
|
|
176
|
+
info: InfoCircleIcon,
|
|
177
|
+
custom: BellIcon
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* @param {string} prefix - String to prefix ID with
|
|
182
|
+
*/
|
|
183
|
+
function getUniqueId(prefix = 'pf') {
|
|
184
|
+
const uid = new Date().getTime() + Math.random().toString(36).slice(2);
|
|
185
|
+
return `${prefix}-${uid}`;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* This function is a helper for turning arrays of breakpointMod objects for flex and grid into style object
|
|
189
|
+
*
|
|
190
|
+
* @param {object} mods The modifiers object
|
|
191
|
+
* @param {string} css-variable The appropriate css variable for the component
|
|
192
|
+
*/
|
|
193
|
+
const setBreakpointCssVars = (mods, cssVar) => Object.entries(mods || {}).reduce((acc, [breakpoint, value]) => breakpoint === 'default' ? Object.assign(Object.assign({}, acc), { [cssVar]: value }) : Object.assign(Object.assign({}, acc), { [`${cssVar}-on-${breakpoint}`]: value }), {});
|
|
194
|
+
/**
|
|
195
|
+
* This function is a helper for turning arrays of breakpointMod objects for data toolbar and flex into classes
|
|
196
|
+
*
|
|
197
|
+
* @param {object} mods The modifiers object
|
|
198
|
+
* @param {any} styles The appropriate styles object for the component
|
|
199
|
+
*/
|
|
200
|
+
const formatBreakpointMods = (mods, styles, stylePrefix = '', breakpoint, vertical) => {
|
|
201
|
+
if (!mods) {
|
|
202
|
+
return '';
|
|
203
|
+
}
|
|
204
|
+
if (breakpoint && !vertical) {
|
|
205
|
+
if (breakpoint in mods) {
|
|
206
|
+
return styles.modifiers[toCamel(`${stylePrefix}${mods[breakpoint]}`)];
|
|
207
|
+
}
|
|
208
|
+
// the current breakpoint is not specified in mods, so we try to find the next nearest
|
|
209
|
+
const breakpointsOrder = ['2xl', 'xl', 'lg', 'md', 'sm', 'default'];
|
|
210
|
+
const breakpointsIndex = breakpointsOrder.indexOf(breakpoint);
|
|
211
|
+
for (let i = breakpointsIndex; i < breakpointsOrder.length; i++) {
|
|
212
|
+
if (breakpointsOrder[i] in mods) {
|
|
213
|
+
return styles.modifiers[toCamel(`${stylePrefix}${mods[breakpointsOrder[i]]}`)];
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return '';
|
|
217
|
+
}
|
|
218
|
+
return Object.entries(mods || {})
|
|
219
|
+
.map(([breakpoint, mod]) => `${stylePrefix}${mod}${breakpoint !== 'default' ? `-on-${breakpoint}` : ''}${vertical && breakpoint !== 'default' ? '-height' : ''}`)
|
|
220
|
+
.map(toCamel)
|
|
221
|
+
.map((mod) => mod.replace(/-?(\dxl)/gi, (_res, group) => `_${group}`))
|
|
222
|
+
.map((modifierKey) => styles.modifiers[modifierKey])
|
|
223
|
+
.filter(Boolean)
|
|
224
|
+
.join(' ');
|
|
225
|
+
};
|
|
226
|
+
/**
|
|
227
|
+
* Return the breakpoint for the given height
|
|
228
|
+
*
|
|
229
|
+
* @param {number | null} height The height to check
|
|
230
|
+
* @returns {'default' | 'sm' | 'md' | 'lg' | 'xl' | '2xl'} The breakpoint
|
|
231
|
+
*/
|
|
232
|
+
const getVerticalBreakpoint = (height) => {
|
|
233
|
+
if (height === null) {
|
|
234
|
+
return null;
|
|
235
|
+
}
|
|
236
|
+
if (height >= globalHeightBreakpoints['2xl']) {
|
|
237
|
+
return '2xl';
|
|
238
|
+
}
|
|
239
|
+
if (height >= globalHeightBreakpoints.xl) {
|
|
240
|
+
return 'xl';
|
|
241
|
+
}
|
|
242
|
+
if (height >= globalHeightBreakpoints.lg) {
|
|
243
|
+
return 'lg';
|
|
244
|
+
}
|
|
245
|
+
if (height >= globalHeightBreakpoints.md) {
|
|
246
|
+
return 'md';
|
|
247
|
+
}
|
|
248
|
+
if (height >= globalHeightBreakpoints.sm) {
|
|
249
|
+
return 'sm';
|
|
250
|
+
}
|
|
251
|
+
return 'default';
|
|
252
|
+
};
|
|
253
|
+
/**
|
|
254
|
+
* Return the breakpoint for the given width
|
|
255
|
+
*
|
|
256
|
+
* @param {number | null} width The width to check
|
|
257
|
+
* @returns {'default' | 'sm' | 'md' | 'lg' | 'xl' | '2xl'} The breakpoint
|
|
258
|
+
*/
|
|
259
|
+
const getBreakpoint = (width) => {
|
|
260
|
+
if (width === null) {
|
|
261
|
+
return null;
|
|
262
|
+
}
|
|
263
|
+
if (width >= globalWidthBreakpoints['2xl']) {
|
|
264
|
+
return '2xl';
|
|
265
|
+
}
|
|
266
|
+
if (width >= globalWidthBreakpoints.xl) {
|
|
267
|
+
return 'xl';
|
|
268
|
+
}
|
|
269
|
+
if (width >= globalWidthBreakpoints.lg) {
|
|
270
|
+
return 'lg';
|
|
271
|
+
}
|
|
272
|
+
if (width >= globalWidthBreakpoints.md) {
|
|
273
|
+
return 'md';
|
|
274
|
+
}
|
|
275
|
+
if (width >= globalWidthBreakpoints.sm) {
|
|
276
|
+
return 'sm';
|
|
277
|
+
}
|
|
278
|
+
return 'default';
|
|
279
|
+
};
|
|
280
|
+
const camelize = (s) => s.toUpperCase().replace('-', '').replace('_', '');
|
|
281
|
+
/**
|
|
282
|
+
*
|
|
283
|
+
* @param {string} s string to make camelCased
|
|
284
|
+
*/
|
|
285
|
+
const toCamel = (s) => s.replace(/([-_][a-z])/gi, camelize);
|
|
286
|
+
/**
|
|
287
|
+
* Copied from exenv
|
|
288
|
+
*/
|
|
289
|
+
const canUseDOM = !!(typeof window !== 'undefined' && window.document && window.document.createElement);
|
|
290
|
+
/**
|
|
291
|
+
* Calculate the width of the text
|
|
292
|
+
* Example:
|
|
293
|
+
* getTextWidth('my text', node)
|
|
294
|
+
*
|
|
295
|
+
* @param {string} text The text to calculate the width for
|
|
296
|
+
* @param {HTMLElement} node The HTML element
|
|
297
|
+
*/
|
|
298
|
+
const getTextWidth = (text, node) => {
|
|
299
|
+
const computedStyle = getComputedStyle(node);
|
|
300
|
+
// Firefox returns the empty string for .font, so this function creates the .font property manually
|
|
301
|
+
const getFontFromComputedStyle = () => {
|
|
302
|
+
let computedFont = '';
|
|
303
|
+
// Firefox uses percentages for font-stretch, but Canvas does not accept percentages
|
|
304
|
+
// so convert to keywords, as listed at:
|
|
305
|
+
// https://developer.mozilla.org/en-US/docs/Web/CSS/font-stretch
|
|
306
|
+
const fontStretchLookupTable = {
|
|
307
|
+
'50%': 'ultra-condensed',
|
|
308
|
+
'62.5%': 'extra-condensed',
|
|
309
|
+
'75%': 'condensed',
|
|
310
|
+
'87.5%': 'semi-condensed',
|
|
311
|
+
'100%': 'normal',
|
|
312
|
+
'112.5%': 'semi-expanded',
|
|
313
|
+
'125%': 'expanded',
|
|
314
|
+
'150%': 'extra-expanded',
|
|
315
|
+
'200%': 'ultra-expanded'
|
|
316
|
+
};
|
|
317
|
+
// If the retrieved font-stretch percentage isn't found in the lookup table, use
|
|
318
|
+
// 'normal' as a last resort.
|
|
319
|
+
let fontStretch;
|
|
320
|
+
if (computedStyle.fontStretch in fontStretchLookupTable) {
|
|
321
|
+
fontStretch = fontStretchLookupTable[computedStyle.fontStretch];
|
|
322
|
+
}
|
|
323
|
+
else {
|
|
324
|
+
fontStretch = 'normal';
|
|
325
|
+
}
|
|
326
|
+
computedFont =
|
|
327
|
+
computedStyle.fontStyle +
|
|
328
|
+
' ' +
|
|
329
|
+
computedStyle.fontVariant +
|
|
330
|
+
' ' +
|
|
331
|
+
computedStyle.fontWeight +
|
|
332
|
+
' ' +
|
|
333
|
+
fontStretch +
|
|
334
|
+
' ' +
|
|
335
|
+
computedStyle.fontSize +
|
|
336
|
+
'/' +
|
|
337
|
+
computedStyle.lineHeight +
|
|
338
|
+
' ' +
|
|
339
|
+
computedStyle.fontFamily;
|
|
340
|
+
return computedFont;
|
|
341
|
+
};
|
|
342
|
+
const canvas = document.createElement('canvas');
|
|
343
|
+
const context = canvas.getContext('2d');
|
|
344
|
+
context.font = computedStyle.font || getFontFromComputedStyle();
|
|
345
|
+
return context.measureText(text).width;
|
|
346
|
+
};
|
|
347
|
+
/**
|
|
348
|
+
* Get the inner dimensions of an element
|
|
349
|
+
*
|
|
350
|
+
* @param {HTMLElement} node HTML element to calculate the inner dimensions for
|
|
351
|
+
*/
|
|
352
|
+
const innerDimensions = (node) => {
|
|
353
|
+
const computedStyle = getComputedStyle(node);
|
|
354
|
+
let width = node.clientWidth; // width with padding
|
|
355
|
+
let height = node.clientHeight; // height with padding
|
|
356
|
+
height -= parseFloat(computedStyle.paddingTop) + parseFloat(computedStyle.paddingBottom);
|
|
357
|
+
width -= parseFloat(computedStyle.paddingLeft) + parseFloat(computedStyle.paddingRight);
|
|
358
|
+
return { height, width };
|
|
359
|
+
};
|
|
360
|
+
/**
|
|
361
|
+
* This function is a helper for truncating text content on the left, leaving the right side of the content in view
|
|
362
|
+
*
|
|
363
|
+
* @param {HTMLElement} node HTML element
|
|
364
|
+
* @param {string} value The original text value
|
|
365
|
+
*/
|
|
366
|
+
const trimLeft = (node, value) => {
|
|
367
|
+
const availableWidth = innerDimensions(node).width;
|
|
368
|
+
let newValue = value;
|
|
369
|
+
if (getTextWidth(value, node) > availableWidth) {
|
|
370
|
+
// we have text overflow, trim the text to the left and add ... in the front until it fits
|
|
371
|
+
while (getTextWidth(`...${newValue}`, node) > availableWidth) {
|
|
372
|
+
newValue = newValue.substring(1);
|
|
373
|
+
}
|
|
374
|
+
// replace text with our truncated text
|
|
375
|
+
if (node.value) {
|
|
376
|
+
node.value = `...${newValue}`;
|
|
377
|
+
}
|
|
378
|
+
else {
|
|
379
|
+
node.innerText = `...${newValue}`;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
else {
|
|
383
|
+
if (node.value) {
|
|
384
|
+
node.value = value;
|
|
385
|
+
}
|
|
386
|
+
else {
|
|
387
|
+
node.innerText = value;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
};
|
|
391
|
+
/**
|
|
392
|
+
* @param {React.RefObject<any>[]} timeoutRefs - Timeout refs to clear
|
|
393
|
+
*/
|
|
394
|
+
const clearTimeouts = (timeoutRefs) => {
|
|
395
|
+
timeoutRefs.forEach((ref) => {
|
|
396
|
+
if (ref.current) {
|
|
397
|
+
clearTimeout(ref.current);
|
|
398
|
+
}
|
|
399
|
+
});
|
|
400
|
+
};
|
|
401
|
+
/**
|
|
402
|
+
* Helper function to get the language direction of a given element, useful for figuring out if left-to-right
|
|
403
|
+
* or right-to-left specific logic should be applied.
|
|
404
|
+
*
|
|
405
|
+
* @param {HTMLElement} targetElement - Element the helper will get the language direction of
|
|
406
|
+
* @param {'ltr' | 'rtl'} defaultDirection - Language direction to assume if one can't be determined, defaults to 'ltr'
|
|
407
|
+
* @returns {'ltr' | 'rtl'} - The language direction of the target element
|
|
408
|
+
*/
|
|
409
|
+
const getLanguageDirection = (targetElement, defaultDirection = 'ltr') => {
|
|
410
|
+
if (!targetElement) {
|
|
411
|
+
return defaultDirection;
|
|
412
|
+
}
|
|
413
|
+
const computedDirection = getComputedStyle(targetElement).getPropertyValue('direction');
|
|
414
|
+
if (['ltr', 'rtl'].includes(computedDirection)) {
|
|
415
|
+
return computedDirection;
|
|
416
|
+
}
|
|
417
|
+
return defaultDirection;
|
|
418
|
+
};
|
|
419
|
+
|
|
420
|
+
/** This Component can be used to wrap a functional component in order to generate a random ID
|
|
421
|
+
* Example of how to use this component
|
|
422
|
+
*
|
|
423
|
+
* const Component = ({id}: {id: string}) => (
|
|
424
|
+
* <GenerateId>{randomId => (
|
|
425
|
+
* <div id={id || randomId}>
|
|
426
|
+
* div with random ID
|
|
427
|
+
* </div>
|
|
428
|
+
* )}
|
|
429
|
+
* </GenerateId>
|
|
430
|
+
* );
|
|
431
|
+
*/
|
|
432
|
+
let currentId = 0;
|
|
433
|
+
// gives us a unique (enough) id to add to the generated id that it should prevent issues with duplicate ids
|
|
434
|
+
function getRandomId() {
|
|
435
|
+
if (typeof crypto !== 'undefined' && crypto.randomUUID) {
|
|
436
|
+
return crypto.randomUUID();
|
|
437
|
+
}
|
|
438
|
+
else {
|
|
439
|
+
return getUniqueId();
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
class GenerateId extends React.Component {
|
|
443
|
+
constructor() {
|
|
444
|
+
super(...arguments);
|
|
445
|
+
this.uniqueElement = this.props.isRandom ? getRandomId() : currentId++;
|
|
446
|
+
this.id = `${this.props.prefix}${this.uniqueElement}`;
|
|
447
|
+
}
|
|
448
|
+
render() {
|
|
449
|
+
return this.props.children(this.id);
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
GenerateId.displayName = 'GenerateId';
|
|
453
|
+
GenerateId.defaultProps = {
|
|
454
|
+
prefix: 'pf-random-id-',
|
|
455
|
+
isRandom: false
|
|
456
|
+
};
|
|
457
|
+
|
|
458
|
+
const ASTERISK = '*';
|
|
459
|
+
|
|
460
|
+
let uid = 0;
|
|
461
|
+
const ouiaPrefix = 'OUIA-Generated-';
|
|
462
|
+
const ouiaIdByRoute = {};
|
|
463
|
+
/** Get props to conform to OUIA spec
|
|
464
|
+
*
|
|
465
|
+
* For functional components, use the useOUIAProps function instead
|
|
466
|
+
*
|
|
467
|
+
* In class based components, create a state variable ouiaStateId to create a static generated ID:
|
|
468
|
+
* state = {
|
|
469
|
+
* ouiaStateId: getDefaultOUIAId(Chip.displayName)
|
|
470
|
+
* }
|
|
471
|
+
* This generated ID should remain alive as long as the component is not unmounted.
|
|
472
|
+
*
|
|
473
|
+
* Then add the attributes to the component
|
|
474
|
+
* {...getOUIAProps('OverflowChip', this.props.ouiaId !== undefined ? this.props.ouiaId : this.state.ouiaStateId)}
|
|
475
|
+
*
|
|
476
|
+
* @param {string} componentType OUIA component type
|
|
477
|
+
* @param {number|string} id OUIA component id
|
|
478
|
+
* @param {boolean} ouiaSafe false if in animation
|
|
479
|
+
*/
|
|
480
|
+
function getOUIAProps(componentType, id, ouiaSafe = true) {
|
|
481
|
+
return {
|
|
482
|
+
'data-ouia-component-type': `PF6/${componentType}`,
|
|
483
|
+
'data-ouia-safe': ouiaSafe,
|
|
484
|
+
'data-ouia-component-id': id
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* Hooks version of the getOUIAProps function that also memoizes the generated ID
|
|
489
|
+
* Can only be used in functional components
|
|
490
|
+
*
|
|
491
|
+
* @param {string} componentType OUIA component type
|
|
492
|
+
* @param {number|string} id OUIA component id
|
|
493
|
+
* @param {boolean} ouiaSafe false if in animation
|
|
494
|
+
* @param {string} variant Optional variant to add to the generated ID
|
|
495
|
+
*/
|
|
496
|
+
const useOUIAProps = (componentType, id, ouiaSafe = true, variant) => ({
|
|
497
|
+
'data-ouia-component-type': `PF6/${componentType}`,
|
|
498
|
+
'data-ouia-safe': ouiaSafe,
|
|
499
|
+
'data-ouia-component-id': useOUIAId(componentType, id, variant)
|
|
500
|
+
});
|
|
501
|
+
/**
|
|
502
|
+
* Returns the ID or the memoized generated ID
|
|
503
|
+
*
|
|
504
|
+
* @param {string} componentType OUIA component type
|
|
505
|
+
* @param {number|string} id OUIA component id
|
|
506
|
+
* @param {string} variant Optional variant to add to the generated ID
|
|
507
|
+
*/
|
|
508
|
+
const useOUIAId = (componentType, id, variant) => {
|
|
509
|
+
const defaultOUIAId = useMemo(() => getDefaultOUIAId(componentType, variant), [componentType, variant]);
|
|
510
|
+
return id !== null && id !== void 0 ? id : defaultOUIAId;
|
|
511
|
+
};
|
|
512
|
+
/**
|
|
513
|
+
* Returns a generated id based on the URL location
|
|
514
|
+
*
|
|
515
|
+
* @param {string} componentType OUIA component type
|
|
516
|
+
* @param {string} variant Optional variant to add to the generated ID
|
|
517
|
+
*/
|
|
518
|
+
function getDefaultOUIAId(componentType, variant) {
|
|
519
|
+
/*
|
|
520
|
+
ouiaIdByRoute = {
|
|
521
|
+
[route+componentType]: [number]
|
|
522
|
+
}
|
|
523
|
+
*/
|
|
524
|
+
try {
|
|
525
|
+
let key;
|
|
526
|
+
if (typeof window !== 'undefined') {
|
|
527
|
+
// browser environments
|
|
528
|
+
key = `${window.location.href}-${componentType}-${variant || ''}`;
|
|
529
|
+
}
|
|
530
|
+
else {
|
|
531
|
+
// node/SSR environments
|
|
532
|
+
key = `${componentType}-${variant || ''}`;
|
|
533
|
+
}
|
|
534
|
+
if (!ouiaIdByRoute[key]) {
|
|
535
|
+
ouiaIdByRoute[key] = 0;
|
|
536
|
+
}
|
|
537
|
+
return `${ouiaPrefix}${componentType}-${variant ? `${variant}-` : ''}${++ouiaIdByRoute[key]}`;
|
|
538
|
+
}
|
|
539
|
+
catch (exception) {
|
|
540
|
+
return `${ouiaPrefix}${componentType}-${variant ? `${variant}-` : ''}${++uid}`;
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
/**
|
|
545
|
+
* @param element
|
|
546
|
+
*/
|
|
547
|
+
function getBoundingClientRect(element) {
|
|
548
|
+
const rect = element.getBoundingClientRect();
|
|
549
|
+
return {
|
|
550
|
+
width: rect.width,
|
|
551
|
+
height: rect.height,
|
|
552
|
+
top: rect.top,
|
|
553
|
+
right: rect.right,
|
|
554
|
+
bottom: rect.bottom,
|
|
555
|
+
left: rect.left,
|
|
556
|
+
x: rect.left,
|
|
557
|
+
y: rect.top
|
|
558
|
+
};
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
// @ts-nocheck
|
|
562
|
+
/* :: import type { Window } from '../types'; */
|
|
563
|
+
/* :: declare function getWindow(node: Node | Window): Window; */
|
|
564
|
+
/**
|
|
565
|
+
* @param node
|
|
566
|
+
*/
|
|
567
|
+
function getWindow(node) {
|
|
568
|
+
if (node.toString() !== '[object Window]') {
|
|
569
|
+
const ownerDocument = node.ownerDocument;
|
|
570
|
+
return ownerDocument ? ownerDocument.defaultView : window;
|
|
571
|
+
}
|
|
572
|
+
return node;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
// @ts-nocheck
|
|
576
|
+
/**
|
|
577
|
+
* @param node
|
|
578
|
+
*/
|
|
579
|
+
function getWindowScroll(node) {
|
|
580
|
+
const win = getWindow(node);
|
|
581
|
+
const scrollLeft = win.pageXOffset;
|
|
582
|
+
const scrollTop = win.pageYOffset;
|
|
583
|
+
return {
|
|
584
|
+
scrollLeft,
|
|
585
|
+
scrollTop
|
|
586
|
+
};
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
// @ts-nocheck
|
|
590
|
+
/* :: declare function isElement(node: mixed): boolean %checks(node instanceof
|
|
591
|
+
Element); */
|
|
592
|
+
/**
|
|
593
|
+
* @param node
|
|
594
|
+
*/
|
|
595
|
+
function isElement(node) {
|
|
596
|
+
const OwnElement = getWindow(node).Element;
|
|
597
|
+
return node instanceof OwnElement || node instanceof Element;
|
|
598
|
+
}
|
|
599
|
+
/* :: declare function isHTMLElement(node: mixed): boolean %checks(node instanceof
|
|
600
|
+
HTMLElement); */
|
|
601
|
+
/**
|
|
602
|
+
* @param node
|
|
603
|
+
*/
|
|
604
|
+
function isHTMLElement(node) {
|
|
605
|
+
const OwnElement = getWindow(node).HTMLElement;
|
|
606
|
+
return node instanceof OwnElement || node instanceof HTMLElement;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
// @ts-nocheck
|
|
610
|
+
/**
|
|
611
|
+
* @param element
|
|
612
|
+
*/
|
|
613
|
+
function getHTMLElementScroll(element) {
|
|
614
|
+
return {
|
|
615
|
+
scrollLeft: element.scrollLeft,
|
|
616
|
+
scrollTop: element.scrollTop
|
|
617
|
+
};
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
// @ts-nocheck
|
|
621
|
+
/**
|
|
622
|
+
* @param node
|
|
623
|
+
*/
|
|
624
|
+
function getNodeScroll(node) {
|
|
625
|
+
if (node === getWindow(node) || !isHTMLElement(node)) {
|
|
626
|
+
return getWindowScroll(node);
|
|
627
|
+
}
|
|
628
|
+
else {
|
|
629
|
+
return getHTMLElementScroll(node);
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
/**
|
|
634
|
+
* @param element
|
|
635
|
+
*/
|
|
636
|
+
function getNodeName(element) {
|
|
637
|
+
return element ? (element.nodeName || '').toLowerCase() : null;
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
// @ts-nocheck
|
|
641
|
+
/**
|
|
642
|
+
* @param element
|
|
643
|
+
*/
|
|
644
|
+
function getDocumentElement(element) {
|
|
645
|
+
// $FlowFixMe: assume body is always available
|
|
646
|
+
return (isElement(element) ? element.ownerDocument : element.document).documentElement;
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
// @ts-nocheck
|
|
650
|
+
/**
|
|
651
|
+
* @param element
|
|
652
|
+
*/
|
|
653
|
+
function getWindowScrollBarX(element) {
|
|
654
|
+
// If <html> has a CSS width greater than the viewport, then this will be
|
|
655
|
+
// incorrect for RTL.
|
|
656
|
+
// Popper 1 is broken in this case and never had a bug report so let's assume
|
|
657
|
+
// it's not an issue. I don't think anyone ever specifies width on <html>
|
|
658
|
+
// anyway.
|
|
659
|
+
// Browsers where the left scrollbar doesn't cause an issue report `0` for
|
|
660
|
+
// this (e.g. Edge 2019, IE11, Safari)
|
|
661
|
+
return getBoundingClientRect(getDocumentElement(element)).left + getWindowScroll(element).scrollLeft;
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
// @ts-nocheck
|
|
665
|
+
/**
|
|
666
|
+
* @param element
|
|
667
|
+
*/
|
|
668
|
+
function getComputedStyle$1(element) {
|
|
669
|
+
return getWindow(element).getComputedStyle(element);
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
// @ts-nocheck
|
|
673
|
+
/**
|
|
674
|
+
* @param element
|
|
675
|
+
*/
|
|
676
|
+
function isScrollParent(element) {
|
|
677
|
+
// Firefox wants us to check `-x` and `-y` variations as well
|
|
678
|
+
const { overflow, overflowX, overflowY } = getComputedStyle$1(element);
|
|
679
|
+
return /auto|scroll|overlay|hidden/.test(overflow + overflowY + overflowX);
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
// Returns the composite rect of an element relative to its offsetParent.
|
|
683
|
+
// Composite means it takes into account transforms as well as layout.
|
|
684
|
+
/**
|
|
685
|
+
* @param elementOrVirtualElement
|
|
686
|
+
* @param offsetParent
|
|
687
|
+
* @param isFixed
|
|
688
|
+
*/
|
|
689
|
+
function getCompositeRect(elementOrVirtualElement, offsetParent, isFixed = false) {
|
|
690
|
+
const documentElement = getDocumentElement(offsetParent);
|
|
691
|
+
const rect = getBoundingClientRect(elementOrVirtualElement);
|
|
692
|
+
const isOffsetParentAnElement = isHTMLElement(offsetParent);
|
|
693
|
+
let scroll = { scrollLeft: 0, scrollTop: 0 };
|
|
694
|
+
let offsets = { x: 0, y: 0 };
|
|
695
|
+
if (isOffsetParentAnElement || (!isOffsetParentAnElement && !isFixed)) {
|
|
696
|
+
if (getNodeName(offsetParent) !== 'body' || // https://github.com/popperjs/popper-core/issues/1078
|
|
697
|
+
isScrollParent(documentElement)) {
|
|
698
|
+
scroll = getNodeScroll(offsetParent);
|
|
699
|
+
}
|
|
700
|
+
if (isHTMLElement(offsetParent)) {
|
|
701
|
+
offsets = getBoundingClientRect(offsetParent);
|
|
702
|
+
offsets.x += offsetParent.clientLeft;
|
|
703
|
+
offsets.y += offsetParent.clientTop;
|
|
704
|
+
}
|
|
705
|
+
else if (documentElement) {
|
|
706
|
+
offsets.x = getWindowScrollBarX(documentElement);
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
return {
|
|
710
|
+
x: rect.left + scroll.scrollLeft - offsets.x,
|
|
711
|
+
y: rect.top + scroll.scrollTop - offsets.y,
|
|
712
|
+
width: rect.width,
|
|
713
|
+
height: rect.height
|
|
714
|
+
};
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
// Returns the layout rect of an element relative to its offsetParent. Layout
|
|
718
|
+
// means it doesn't take into account transforms.
|
|
719
|
+
/**
|
|
720
|
+
* @param element
|
|
721
|
+
*/
|
|
722
|
+
function getLayoutRect(element) {
|
|
723
|
+
return {
|
|
724
|
+
x: element.offsetLeft,
|
|
725
|
+
y: element.offsetTop,
|
|
726
|
+
width: element.offsetWidth,
|
|
727
|
+
height: element.offsetHeight
|
|
728
|
+
};
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
// @ts-nocheck
|
|
732
|
+
/**
|
|
733
|
+
* @param element
|
|
734
|
+
*/
|
|
735
|
+
function getParentNode(element) {
|
|
736
|
+
if (getNodeName(element) === 'html') {
|
|
737
|
+
return element;
|
|
738
|
+
}
|
|
739
|
+
return (
|
|
740
|
+
// $FlowFixMe: this is a quicker (but less type safe) way to save quite some bytes from the bundle
|
|
741
|
+
element.assignedSlot || // step into the shadow DOM of the parent of a slotted node
|
|
742
|
+
element.parentNode || // DOM Element detected
|
|
743
|
+
// $FlowFixMe: need a better way to handle this...
|
|
744
|
+
element.host || // ShadowRoot detected
|
|
745
|
+
// $FlowFixMe: HTMLElement is a Node
|
|
746
|
+
getDocumentElement(element) // fallback
|
|
747
|
+
);
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
// @ts-nocheck
|
|
751
|
+
/**
|
|
752
|
+
* @param node
|
|
753
|
+
*/
|
|
754
|
+
function getScrollParent(node) {
|
|
755
|
+
if (['html', 'body', '#document'].indexOf(getNodeName(node)) >= 0) {
|
|
756
|
+
// $FlowFixMe: assume body is always available
|
|
757
|
+
return node.ownerDocument.body;
|
|
758
|
+
}
|
|
759
|
+
if (isHTMLElement(node) && isScrollParent(node)) {
|
|
760
|
+
return node;
|
|
761
|
+
}
|
|
762
|
+
return getScrollParent(getParentNode(node));
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
// @ts-nocheck
|
|
766
|
+
/*
|
|
767
|
+
given a DOM element, return the list of all scroll parents, up the list of ancesors
|
|
768
|
+
until we get to the top window object. This list is what we attach scroll listeners
|
|
769
|
+
to, because if any of these parent elements scroll, we'll need to re-calculate the
|
|
770
|
+
reference element's position.
|
|
771
|
+
*/
|
|
772
|
+
/**
|
|
773
|
+
* @param element
|
|
774
|
+
* @param list
|
|
775
|
+
*/
|
|
776
|
+
function listScrollParents(element, list = []) {
|
|
777
|
+
const scrollParent = getScrollParent(element);
|
|
778
|
+
const isBody = getNodeName(scrollParent) === 'body';
|
|
779
|
+
const win = getWindow(scrollParent);
|
|
780
|
+
const target = isBody
|
|
781
|
+
? [win].concat(win.visualViewport || [], isScrollParent(scrollParent) ? scrollParent : [])
|
|
782
|
+
: scrollParent;
|
|
783
|
+
const updatedList = list.concat(target);
|
|
784
|
+
return isBody
|
|
785
|
+
? updatedList // $FlowFixMe: isBody tells us target will be an HTMLElement here
|
|
786
|
+
: updatedList.concat(listScrollParents(getParentNode(target)));
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
// @ts-nocheck
|
|
790
|
+
/**
|
|
791
|
+
* @param element
|
|
792
|
+
*/
|
|
793
|
+
function isTableElement(element) {
|
|
794
|
+
return ['table', 'td', 'th'].indexOf(getNodeName(element)) >= 0;
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
// @ts-nocheck
|
|
798
|
+
/**
|
|
799
|
+
* @param element
|
|
800
|
+
*/
|
|
801
|
+
function getTrueOffsetParent(element) {
|
|
802
|
+
if (!isHTMLElement(element) || // https://github.com/popperjs/popper-core/issues/837
|
|
803
|
+
getComputedStyle$1(element).position === 'fixed') {
|
|
804
|
+
return null;
|
|
805
|
+
}
|
|
806
|
+
const offsetParent = element.offsetParent;
|
|
807
|
+
if (offsetParent) {
|
|
808
|
+
const html = getDocumentElement(offsetParent);
|
|
809
|
+
if (getNodeName(offsetParent) === 'body' &&
|
|
810
|
+
getComputedStyle$1(offsetParent).position === 'static' &&
|
|
811
|
+
getComputedStyle$1(html).position !== 'static') {
|
|
812
|
+
return html;
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
return offsetParent;
|
|
816
|
+
}
|
|
817
|
+
// `.offsetParent` reports `null` for fixed elements, while absolute elements
|
|
818
|
+
// return the containing block
|
|
819
|
+
/**
|
|
820
|
+
* @param element
|
|
821
|
+
*/
|
|
822
|
+
function getContainingBlock(element) {
|
|
823
|
+
let currentNode = getParentNode(element);
|
|
824
|
+
while (isHTMLElement(currentNode) && ['html', 'body'].indexOf(getNodeName(currentNode)) < 0) {
|
|
825
|
+
const css = getComputedStyle$1(currentNode);
|
|
826
|
+
// This is non-exhaustive but covers the most common CSS properties that
|
|
827
|
+
// create a containing block.
|
|
828
|
+
if (css.transform !== 'none' || css.perspective !== 'none' || (css.willChange && css.willChange !== 'auto')) {
|
|
829
|
+
return currentNode;
|
|
830
|
+
}
|
|
831
|
+
else {
|
|
832
|
+
currentNode = currentNode.parentNode;
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
return null;
|
|
836
|
+
}
|
|
837
|
+
// Gets the closest ancestor positioned element. Handles some edge cases,
|
|
838
|
+
// such as table ancestors and cross browser bugs.
|
|
839
|
+
/**
|
|
840
|
+
* @param element
|
|
841
|
+
*/
|
|
842
|
+
function getOffsetParent(element) {
|
|
843
|
+
const window = getWindow(element);
|
|
844
|
+
let offsetParent = getTrueOffsetParent(element);
|
|
845
|
+
while (offsetParent && isTableElement(offsetParent) && getComputedStyle$1(offsetParent).position === 'static') {
|
|
846
|
+
offsetParent = getTrueOffsetParent(offsetParent);
|
|
847
|
+
}
|
|
848
|
+
if (offsetParent && getNodeName(offsetParent) === 'body' && getComputedStyle$1(offsetParent).position === 'static') {
|
|
849
|
+
return window;
|
|
850
|
+
}
|
|
851
|
+
return offsetParent || getContainingBlock(element) || window;
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
// @ts-nocheck
|
|
855
|
+
const top = 'top';
|
|
856
|
+
const bottom = 'bottom';
|
|
857
|
+
const right = 'right';
|
|
858
|
+
const left = 'left';
|
|
859
|
+
const auto = 'auto';
|
|
860
|
+
const basePlacements = [top, bottom, right, left];
|
|
861
|
+
const start = 'start';
|
|
862
|
+
const end = 'end';
|
|
863
|
+
const clippingParents = 'clippingParents';
|
|
864
|
+
const viewport = 'viewport';
|
|
865
|
+
const popper = 'popper';
|
|
866
|
+
const reference = 'reference';
|
|
867
|
+
const variationPlacements = basePlacements.reduce((acc, placement) => acc.concat([`${placement}-${start}`, `${placement}-${end}`]), []);
|
|
868
|
+
const placements = [...basePlacements, auto].reduce((acc, placement) => acc.concat([placement, `${placement}-${start}`, `${placement}-${end}`]), []);
|
|
869
|
+
// modifiers that need to read the DOM
|
|
870
|
+
const beforeRead = 'beforeRead';
|
|
871
|
+
const read = 'read';
|
|
872
|
+
const afterRead = 'afterRead';
|
|
873
|
+
// pure-logic modifiers
|
|
874
|
+
const beforeMain = 'beforeMain';
|
|
875
|
+
const main = 'main';
|
|
876
|
+
const afterMain = 'afterMain';
|
|
877
|
+
// modifier with the purpose to write to the DOM (or write into a framework state)
|
|
878
|
+
const beforeWrite = 'beforeWrite';
|
|
879
|
+
const write = 'write';
|
|
880
|
+
const afterWrite = 'afterWrite';
|
|
881
|
+
const modifierPhases = [
|
|
882
|
+
beforeRead,
|
|
883
|
+
read,
|
|
884
|
+
afterRead,
|
|
885
|
+
beforeMain,
|
|
886
|
+
main,
|
|
887
|
+
afterMain,
|
|
888
|
+
beforeWrite,
|
|
889
|
+
write,
|
|
890
|
+
afterWrite
|
|
891
|
+
];
|
|
892
|
+
|
|
893
|
+
// source: https://stackoverflow.com/questions/49875255
|
|
894
|
+
/**
|
|
895
|
+
* @param modifiers
|
|
896
|
+
*/
|
|
897
|
+
function order(modifiers) {
|
|
898
|
+
const map = new Map();
|
|
899
|
+
const visited = new Set();
|
|
900
|
+
const result = [];
|
|
901
|
+
modifiers.forEach(modifier => {
|
|
902
|
+
map.set(modifier.name, modifier);
|
|
903
|
+
});
|
|
904
|
+
// On visiting object, check for its dependencies and visit them recursively
|
|
905
|
+
/**
|
|
906
|
+
* @param modifier
|
|
907
|
+
*/
|
|
908
|
+
function sort(modifier) {
|
|
909
|
+
visited.add(modifier.name);
|
|
910
|
+
const requires = [...(modifier.requires || []), ...(modifier.requiresIfExists || [])];
|
|
911
|
+
requires.forEach(dep => {
|
|
912
|
+
if (!visited.has(dep)) {
|
|
913
|
+
const depModifier = map.get(dep);
|
|
914
|
+
if (depModifier) {
|
|
915
|
+
sort(depModifier);
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
});
|
|
919
|
+
result.push(modifier);
|
|
920
|
+
}
|
|
921
|
+
modifiers.forEach(modifier => {
|
|
922
|
+
if (!visited.has(modifier.name)) {
|
|
923
|
+
// check for visited object
|
|
924
|
+
sort(modifier);
|
|
925
|
+
}
|
|
926
|
+
});
|
|
927
|
+
return result;
|
|
928
|
+
}
|
|
929
|
+
/**
|
|
930
|
+
* @param modifiers
|
|
931
|
+
*/
|
|
932
|
+
function orderModifiers(modifiers) {
|
|
933
|
+
// order based on dependencies
|
|
934
|
+
const orderedModifiers = order(modifiers);
|
|
935
|
+
// order based on phase
|
|
936
|
+
return modifierPhases.reduce((acc, phase) => acc.concat(orderedModifiers.filter(modifier => modifier.phase === phase)), []);
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
// @ts-nocheck
|
|
940
|
+
/**
|
|
941
|
+
* @param fn
|
|
942
|
+
*/
|
|
943
|
+
function debounce(fn) {
|
|
944
|
+
let pending;
|
|
945
|
+
return () => {
|
|
946
|
+
if (!pending) {
|
|
947
|
+
pending = new Promise(resolve => {
|
|
948
|
+
Promise.resolve().then(() => {
|
|
949
|
+
pending = undefined;
|
|
950
|
+
resolve(fn());
|
|
951
|
+
});
|
|
952
|
+
});
|
|
953
|
+
}
|
|
954
|
+
return pending;
|
|
955
|
+
};
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
/**
|
|
959
|
+
* @param placement
|
|
960
|
+
*/
|
|
961
|
+
function getBasePlacement(placement) {
|
|
962
|
+
return placement.split('-')[0];
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
/**
|
|
966
|
+
* @param modifiers
|
|
967
|
+
*/
|
|
968
|
+
function mergeByName(modifiers) {
|
|
969
|
+
const merged = modifiers.reduce((merged, current) => {
|
|
970
|
+
const existing = merged[current.name];
|
|
971
|
+
merged[current.name] = existing
|
|
972
|
+
? Object.assign(Object.assign(Object.assign({}, existing), current), { options: Object.assign(Object.assign({}, existing.options), current.options), data: Object.assign(Object.assign({}, existing.data), current.data) }) : current;
|
|
973
|
+
return merged;
|
|
974
|
+
}, {});
|
|
975
|
+
// IE11 does not support Object.values
|
|
976
|
+
return Object.keys(merged).map(key => merged[key]);
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
// @ts-nocheck
|
|
980
|
+
/**
|
|
981
|
+
* @param element
|
|
982
|
+
*/
|
|
983
|
+
function getViewportRect(element) {
|
|
984
|
+
const win = getWindow(element);
|
|
985
|
+
const html = getDocumentElement(element);
|
|
986
|
+
const visualViewport = win.visualViewport;
|
|
987
|
+
let width = html.clientWidth;
|
|
988
|
+
let height = html.clientHeight;
|
|
989
|
+
let x = 0;
|
|
990
|
+
let y = 0;
|
|
991
|
+
// NB: This isn't supported on iOS <= 12. If the keyboard is open, the popper
|
|
992
|
+
// can be obscured underneath it.
|
|
993
|
+
// Also, `html.clientHeight` adds the bottom bar height in Safari iOS, even
|
|
994
|
+
// if it isn't open, so if this isn't available, the popper will be detected
|
|
995
|
+
// to overflow the bottom of the screen too early.
|
|
996
|
+
if (visualViewport) {
|
|
997
|
+
width = visualViewport.width;
|
|
998
|
+
height = visualViewport.height;
|
|
999
|
+
// Uses Layout Viewport (like Chrome; Safari does not currently)
|
|
1000
|
+
// In Chrome, it returns a value very close to 0 (+/-) but contains rounding
|
|
1001
|
+
// errors due to floating point numbers, so we need to check precision.
|
|
1002
|
+
// Safari returns a number <= 0, usually < -1 when pinch-zoomed
|
|
1003
|
+
// Feature detection fails in mobile emulation mode in Chrome.
|
|
1004
|
+
// Math.abs(win.innerWidth / visualViewport.scale - visualViewport.width) <
|
|
1005
|
+
// 0.001
|
|
1006
|
+
// Fallback here: "Not Safari" userAgent
|
|
1007
|
+
if (!/^((?!chrome|android).)*safari/i.test(navigator.userAgent)) {
|
|
1008
|
+
x = visualViewport.offsetLeft;
|
|
1009
|
+
y = visualViewport.offsetTop;
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
return {
|
|
1013
|
+
width,
|
|
1014
|
+
height,
|
|
1015
|
+
x: x + getWindowScrollBarX(element),
|
|
1016
|
+
y
|
|
1017
|
+
};
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
// Gets the entire size of the scrollable document area, even extending outside
|
|
1021
|
+
// of the `<html>` and `<body>` rect bounds if horizontally scrollable
|
|
1022
|
+
/**
|
|
1023
|
+
* @param element
|
|
1024
|
+
*/
|
|
1025
|
+
function getDocumentRect(element) {
|
|
1026
|
+
const html = getDocumentElement(element);
|
|
1027
|
+
const winScroll = getWindowScroll(element);
|
|
1028
|
+
const body = element.ownerDocument.body;
|
|
1029
|
+
const width = Math.max(html.scrollWidth, html.clientWidth, body ? body.scrollWidth : 0, body ? body.clientWidth : 0);
|
|
1030
|
+
const height = Math.max(html.scrollHeight, html.clientHeight, body ? body.scrollHeight : 0, body ? body.clientHeight : 0);
|
|
1031
|
+
let x = -winScroll.scrollLeft + getWindowScrollBarX(element);
|
|
1032
|
+
const y = -winScroll.scrollTop;
|
|
1033
|
+
if (getComputedStyle$1(body || html).direction === 'rtl') {
|
|
1034
|
+
x += Math.max(html.clientWidth, body ? body.clientWidth : 0) - width;
|
|
1035
|
+
}
|
|
1036
|
+
return { width, height, x, y };
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
// @ts-nocheck
|
|
1040
|
+
/**
|
|
1041
|
+
* @param parent
|
|
1042
|
+
* @param child
|
|
1043
|
+
*/
|
|
1044
|
+
function contains(parent, child) {
|
|
1045
|
+
// $FlowFixMe: hasOwnProperty doesn't seem to work in tests
|
|
1046
|
+
const isShadow = Boolean(child.getRootNode && child.getRootNode().host);
|
|
1047
|
+
// First, attempt with faster native method
|
|
1048
|
+
if (parent.contains(child)) {
|
|
1049
|
+
return true;
|
|
1050
|
+
} // then fallback to custom implementation with Shadow DOM support
|
|
1051
|
+
else if (isShadow) {
|
|
1052
|
+
let next = child;
|
|
1053
|
+
do {
|
|
1054
|
+
if (next && parent.isSameNode(next)) {
|
|
1055
|
+
return true;
|
|
1056
|
+
}
|
|
1057
|
+
// $FlowFixMe: need a better way to handle this...
|
|
1058
|
+
next = next.parentNode || next.host;
|
|
1059
|
+
} while (next);
|
|
1060
|
+
}
|
|
1061
|
+
// Give up, the result is false
|
|
1062
|
+
return false;
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
/**
|
|
1066
|
+
* @param rect
|
|
1067
|
+
*/
|
|
1068
|
+
function rectToClientRect(rect) {
|
|
1069
|
+
return Object.assign(Object.assign({}, rect), { left: rect.x, top: rect.y, right: rect.x + rect.width, bottom: rect.y + rect.height });
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
/**
|
|
1073
|
+
* @param element
|
|
1074
|
+
*/
|
|
1075
|
+
function getInnerBoundingClientRect(element) {
|
|
1076
|
+
const rect = getBoundingClientRect(element);
|
|
1077
|
+
rect.top = rect.top + element.clientTop;
|
|
1078
|
+
rect.left = rect.left + element.clientLeft;
|
|
1079
|
+
rect.bottom = rect.top + element.clientHeight;
|
|
1080
|
+
rect.right = rect.left + element.clientWidth;
|
|
1081
|
+
rect.width = element.clientWidth;
|
|
1082
|
+
rect.height = element.clientHeight;
|
|
1083
|
+
rect.x = rect.left;
|
|
1084
|
+
rect.y = rect.top;
|
|
1085
|
+
return rect;
|
|
1086
|
+
}
|
|
1087
|
+
/**
|
|
1088
|
+
* @param element
|
|
1089
|
+
* @param clippingParent
|
|
1090
|
+
*/
|
|
1091
|
+
function getClientRectFromMixedType(element, clippingParent) {
|
|
1092
|
+
return clippingParent === viewport
|
|
1093
|
+
? rectToClientRect(getViewportRect(element))
|
|
1094
|
+
: isHTMLElement(clippingParent)
|
|
1095
|
+
? getInnerBoundingClientRect(clippingParent)
|
|
1096
|
+
: rectToClientRect(getDocumentRect(getDocumentElement(element)));
|
|
1097
|
+
}
|
|
1098
|
+
// A "clipping parent" is an overflowable container with the characteristic of
|
|
1099
|
+
// clipping (or hiding) overflowing elements with a position different from
|
|
1100
|
+
// `initial`
|
|
1101
|
+
/**
|
|
1102
|
+
* @param element
|
|
1103
|
+
*/
|
|
1104
|
+
function getClippingParents(element) {
|
|
1105
|
+
const clippingParents = listScrollParents(getParentNode(element));
|
|
1106
|
+
const canEscapeClipping = ['absolute', 'fixed'].indexOf(getComputedStyle$1(element).position) >= 0;
|
|
1107
|
+
const clipperElement = canEscapeClipping && isHTMLElement(element) ? getOffsetParent(element) : element;
|
|
1108
|
+
if (!isElement(clipperElement)) {
|
|
1109
|
+
return [];
|
|
1110
|
+
}
|
|
1111
|
+
// $FlowFixMe: https://github.com/facebook/flow/issues/1414
|
|
1112
|
+
return clippingParents.filter(clippingParent => isElement(clippingParent) && contains(clippingParent, clipperElement) && getNodeName(clippingParent) !== 'body');
|
|
1113
|
+
}
|
|
1114
|
+
// Gets the maximum area that the element is visible in due to any number of
|
|
1115
|
+
// clipping parents
|
|
1116
|
+
/**
|
|
1117
|
+
* @param element
|
|
1118
|
+
* @param boundary
|
|
1119
|
+
* @param rootBoundary
|
|
1120
|
+
*/
|
|
1121
|
+
function getClippingRect(element, boundary, rootBoundary) {
|
|
1122
|
+
const mainClippingParents = boundary === 'clippingParents' ? getClippingParents(element) : [].concat(boundary);
|
|
1123
|
+
const clippingParents = [...mainClippingParents, rootBoundary];
|
|
1124
|
+
const firstClippingParent = clippingParents[0];
|
|
1125
|
+
const clippingRect = clippingParents.reduce((accRect, clippingParent) => {
|
|
1126
|
+
const rect = getClientRectFromMixedType(element, clippingParent);
|
|
1127
|
+
accRect.top = Math.max(rect.top, accRect.top);
|
|
1128
|
+
accRect.right = Math.min(rect.right, accRect.right);
|
|
1129
|
+
accRect.bottom = Math.min(rect.bottom, accRect.bottom);
|
|
1130
|
+
accRect.left = Math.max(rect.left, accRect.left);
|
|
1131
|
+
return accRect;
|
|
1132
|
+
}, getClientRectFromMixedType(element, firstClippingParent));
|
|
1133
|
+
clippingRect.width = clippingRect.right - clippingRect.left;
|
|
1134
|
+
clippingRect.height = clippingRect.bottom - clippingRect.top;
|
|
1135
|
+
clippingRect.x = clippingRect.left;
|
|
1136
|
+
clippingRect.y = clippingRect.top;
|
|
1137
|
+
return clippingRect;
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
/**
|
|
1141
|
+
* @param placement
|
|
1142
|
+
*/
|
|
1143
|
+
function getVariation(placement) {
|
|
1144
|
+
return placement.split('-')[1];
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
/**
|
|
1148
|
+
* @param placement
|
|
1149
|
+
*/
|
|
1150
|
+
function getMainAxisFromPlacement(placement) {
|
|
1151
|
+
return ['top', 'bottom'].indexOf(placement) >= 0 ? 'x' : 'y';
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1154
|
+
// @ts-nocheck
|
|
1155
|
+
/**
|
|
1156
|
+
*
|
|
1157
|
+
*/
|
|
1158
|
+
function computeOffsets({ reference, element, placement }) {
|
|
1159
|
+
const basePlacement = placement ? getBasePlacement(placement) : null;
|
|
1160
|
+
const variation = placement ? getVariation(placement) : null;
|
|
1161
|
+
const commonX = reference.x + reference.width / 2 - element.width / 2;
|
|
1162
|
+
const commonY = reference.y + reference.height / 2 - element.height / 2;
|
|
1163
|
+
let offsets;
|
|
1164
|
+
switch (basePlacement) {
|
|
1165
|
+
case top:
|
|
1166
|
+
offsets = {
|
|
1167
|
+
x: commonX,
|
|
1168
|
+
y: reference.y - element.height
|
|
1169
|
+
};
|
|
1170
|
+
break;
|
|
1171
|
+
case bottom:
|
|
1172
|
+
offsets = {
|
|
1173
|
+
x: commonX,
|
|
1174
|
+
y: reference.y + reference.height
|
|
1175
|
+
};
|
|
1176
|
+
break;
|
|
1177
|
+
case right:
|
|
1178
|
+
offsets = {
|
|
1179
|
+
x: reference.x + reference.width,
|
|
1180
|
+
y: commonY
|
|
1181
|
+
};
|
|
1182
|
+
break;
|
|
1183
|
+
case left:
|
|
1184
|
+
offsets = {
|
|
1185
|
+
x: reference.x - element.width,
|
|
1186
|
+
y: commonY
|
|
1187
|
+
};
|
|
1188
|
+
break;
|
|
1189
|
+
default:
|
|
1190
|
+
offsets = {
|
|
1191
|
+
x: reference.x,
|
|
1192
|
+
y: reference.y
|
|
1193
|
+
};
|
|
1194
|
+
}
|
|
1195
|
+
const mainAxis = basePlacement ? getMainAxisFromPlacement(basePlacement) : null;
|
|
1196
|
+
if (mainAxis != null) {
|
|
1197
|
+
const len = mainAxis === 'y' ? 'height' : 'width';
|
|
1198
|
+
switch (variation) {
|
|
1199
|
+
case start:
|
|
1200
|
+
offsets[mainAxis] = Math.floor(offsets[mainAxis]) - Math.floor(reference[len] / 2 - element[len] / 2);
|
|
1201
|
+
break;
|
|
1202
|
+
case end:
|
|
1203
|
+
offsets[mainAxis] = Math.floor(offsets[mainAxis]) + Math.ceil(reference[len] / 2 - element[len] / 2);
|
|
1204
|
+
break;
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
return offsets;
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
/**
|
|
1211
|
+
*
|
|
1212
|
+
*/
|
|
1213
|
+
function getFreshSideObject() {
|
|
1214
|
+
return {
|
|
1215
|
+
top: 0,
|
|
1216
|
+
right: 0,
|
|
1217
|
+
bottom: 0,
|
|
1218
|
+
left: 0
|
|
1219
|
+
};
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
/**
|
|
1223
|
+
* @param paddingObject
|
|
1224
|
+
*/
|
|
1225
|
+
function mergePaddingObject(paddingObject) {
|
|
1226
|
+
return Object.assign(Object.assign({}, getFreshSideObject()), paddingObject);
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
// @ts-nocheck
|
|
1230
|
+
/**
|
|
1231
|
+
* @param value
|
|
1232
|
+
* @param keys
|
|
1233
|
+
*/
|
|
1234
|
+
function expandToHashMap(value, keys) {
|
|
1235
|
+
return keys.reduce((hashMap, key) => {
|
|
1236
|
+
hashMap[key] = value;
|
|
1237
|
+
return hashMap;
|
|
1238
|
+
}, {});
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
/**
|
|
1242
|
+
* @param state
|
|
1243
|
+
* @param options
|
|
1244
|
+
*/
|
|
1245
|
+
function detectOverflow(state, options = {}) {
|
|
1246
|
+
const { placement = state.placement, boundary = clippingParents, rootBoundary = viewport, elementContext = popper, altBoundary = false, padding = 0 } = options;
|
|
1247
|
+
const paddingObject = mergePaddingObject(typeof padding !== 'number' ? padding : expandToHashMap(padding, basePlacements));
|
|
1248
|
+
const altContext = elementContext === popper ? reference : popper;
|
|
1249
|
+
const referenceElement = state.elements.reference;
|
|
1250
|
+
const popperRect = state.rects.popper;
|
|
1251
|
+
const element = state.elements[altBoundary ? altContext : elementContext];
|
|
1252
|
+
const clippingClientRect = getClippingRect(isElement(element) ? element : element.contextElement || getDocumentElement(state.elements.popper), boundary, rootBoundary);
|
|
1253
|
+
const referenceClientRect = getBoundingClientRect(referenceElement);
|
|
1254
|
+
const popperOffsets = computeOffsets({
|
|
1255
|
+
reference: referenceClientRect,
|
|
1256
|
+
element: popperRect,
|
|
1257
|
+
placement
|
|
1258
|
+
});
|
|
1259
|
+
const popperClientRect = rectToClientRect(Object.assign(Object.assign({}, popperRect), popperOffsets));
|
|
1260
|
+
const elementClientRect = elementContext === popper ? popperClientRect : referenceClientRect;
|
|
1261
|
+
// positive = overflowing the clipping rect
|
|
1262
|
+
// 0 or negative = within the clipping rect
|
|
1263
|
+
const overflowOffsets = {
|
|
1264
|
+
top: clippingClientRect.top - elementClientRect.top + paddingObject.top,
|
|
1265
|
+
bottom: elementClientRect.bottom - clippingClientRect.bottom + paddingObject.bottom,
|
|
1266
|
+
left: clippingClientRect.left - elementClientRect.left + paddingObject.left,
|
|
1267
|
+
right: elementClientRect.right - clippingClientRect.right + paddingObject.right
|
|
1268
|
+
};
|
|
1269
|
+
const offsetData = state.modifiersData.offset;
|
|
1270
|
+
// Offsets can be applied only to the popper element
|
|
1271
|
+
if (elementContext === popper && offsetData) {
|
|
1272
|
+
const offset = offsetData[placement];
|
|
1273
|
+
Object.keys(overflowOffsets).forEach(key => {
|
|
1274
|
+
const multiply = [right, bottom].indexOf(key) >= 0 ? 1 : -1;
|
|
1275
|
+
const axis = [top, bottom].indexOf(key) >= 0 ? 'y' : 'x';
|
|
1276
|
+
overflowOffsets[key] += offset[axis] * multiply;
|
|
1277
|
+
});
|
|
1278
|
+
}
|
|
1279
|
+
return overflowOffsets;
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1282
|
+
const DEFAULT_OPTIONS = {
|
|
1283
|
+
placement: 'bottom',
|
|
1284
|
+
modifiers: [],
|
|
1285
|
+
strategy: 'absolute'
|
|
1286
|
+
};
|
|
1287
|
+
/**
|
|
1288
|
+
* @param args
|
|
1289
|
+
*/
|
|
1290
|
+
function areValidElements(...args) {
|
|
1291
|
+
return !args.some(element => !(element && typeof element.getBoundingClientRect === 'function'));
|
|
1292
|
+
}
|
|
1293
|
+
/**
|
|
1294
|
+
* @param generatorOptions
|
|
1295
|
+
*/
|
|
1296
|
+
function popperGenerator(generatorOptions = {}) {
|
|
1297
|
+
const { defaultModifiers = [], defaultOptions = DEFAULT_OPTIONS } = generatorOptions;
|
|
1298
|
+
return function createPopper(reference, popper, options = defaultOptions) {
|
|
1299
|
+
let state = {
|
|
1300
|
+
placement: 'bottom',
|
|
1301
|
+
orderedModifiers: [],
|
|
1302
|
+
options: Object.assign(Object.assign({}, DEFAULT_OPTIONS), defaultOptions),
|
|
1303
|
+
modifiersData: {},
|
|
1304
|
+
elements: {
|
|
1305
|
+
reference,
|
|
1306
|
+
popper
|
|
1307
|
+
},
|
|
1308
|
+
attributes: {},
|
|
1309
|
+
styles: {}
|
|
1310
|
+
};
|
|
1311
|
+
let effectCleanupFns = [];
|
|
1312
|
+
let isDestroyed = false;
|
|
1313
|
+
const instance = {
|
|
1314
|
+
state,
|
|
1315
|
+
setOptions(options) {
|
|
1316
|
+
cleanupModifierEffects();
|
|
1317
|
+
state.options = Object.assign(Object.assign(Object.assign({}, defaultOptions), state.options), options);
|
|
1318
|
+
state.scrollParents = {
|
|
1319
|
+
reference: isElement(reference)
|
|
1320
|
+
? listScrollParents(reference)
|
|
1321
|
+
: reference.contextElement
|
|
1322
|
+
? listScrollParents(reference.contextElement)
|
|
1323
|
+
: [],
|
|
1324
|
+
popper: listScrollParents(popper)
|
|
1325
|
+
};
|
|
1326
|
+
// Orders the modifiers based on their dependencies and `phase`
|
|
1327
|
+
// properties
|
|
1328
|
+
const orderedModifiers = orderModifiers(mergeByName([...defaultModifiers, ...state.options.modifiers]));
|
|
1329
|
+
// Strip out disabled modifiers
|
|
1330
|
+
state.orderedModifiers = orderedModifiers.filter(m => m.enabled);
|
|
1331
|
+
runModifierEffects();
|
|
1332
|
+
return instance.update();
|
|
1333
|
+
},
|
|
1334
|
+
// Sync update – it will always be executed, even if not necessary. This
|
|
1335
|
+
// is useful for low frequency updates where sync behavior simplifies the
|
|
1336
|
+
// logic.
|
|
1337
|
+
// For high frequency updates (e.g. `resize` and `scroll` events), always
|
|
1338
|
+
// prefer the async Popper#update method
|
|
1339
|
+
forceUpdate() {
|
|
1340
|
+
if (isDestroyed) {
|
|
1341
|
+
return;
|
|
1342
|
+
}
|
|
1343
|
+
const { reference, popper } = state.elements;
|
|
1344
|
+
// Don't proceed if `reference` or `popper` are not valid elements
|
|
1345
|
+
// anymore
|
|
1346
|
+
if (!areValidElements(reference, popper)) {
|
|
1347
|
+
return;
|
|
1348
|
+
}
|
|
1349
|
+
// Store the reference and popper rects to be read by modifiers
|
|
1350
|
+
state.rects = {
|
|
1351
|
+
reference: getCompositeRect(reference, getOffsetParent(popper), state.options.strategy === 'fixed'),
|
|
1352
|
+
popper: getLayoutRect(popper)
|
|
1353
|
+
};
|
|
1354
|
+
// Modifiers have the ability to reset the current update cycle. The
|
|
1355
|
+
// most common use case for this is the `flip` modifier changing the
|
|
1356
|
+
// placement, which then needs to re-run all the modifiers, because the
|
|
1357
|
+
// logic was previously ran for the previous placement and is therefore
|
|
1358
|
+
// stale/incorrect
|
|
1359
|
+
state.reset = false;
|
|
1360
|
+
state.placement = state.options.placement;
|
|
1361
|
+
// On each update cycle, the `modifiersData` property for each modifier
|
|
1362
|
+
// is filled with the initial data specified by the modifier. This means
|
|
1363
|
+
// it doesn't persist and is fresh on each update.
|
|
1364
|
+
// To ensure persistent data, use `${name}#persistent`
|
|
1365
|
+
state.orderedModifiers.forEach(modifier => (state.modifiersData[modifier.name] = Object.assign({}, modifier.data)));
|
|
1366
|
+
for (let index = 0; index < state.orderedModifiers.length; index++) {
|
|
1367
|
+
if (state.reset === true) {
|
|
1368
|
+
state.reset = false;
|
|
1369
|
+
index = -1;
|
|
1370
|
+
continue;
|
|
1371
|
+
}
|
|
1372
|
+
const { fn, options = {}, name } = state.orderedModifiers[index];
|
|
1373
|
+
if (typeof fn === 'function') {
|
|
1374
|
+
state = fn({ state, options, name, instance }) || state;
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1377
|
+
},
|
|
1378
|
+
// Async and optimistically optimized update – it will not be executed if
|
|
1379
|
+
// not necessary (debounced to run at most once-per-tick)
|
|
1380
|
+
update: debounce(() => new Promise(resolve => {
|
|
1381
|
+
instance.forceUpdate();
|
|
1382
|
+
resolve(state);
|
|
1383
|
+
})),
|
|
1384
|
+
destroy() {
|
|
1385
|
+
cleanupModifierEffects();
|
|
1386
|
+
isDestroyed = true;
|
|
1387
|
+
}
|
|
1388
|
+
};
|
|
1389
|
+
if (!areValidElements(reference, popper)) {
|
|
1390
|
+
return instance;
|
|
1391
|
+
}
|
|
1392
|
+
instance.setOptions(options).then(state => {
|
|
1393
|
+
if (!isDestroyed && options.onFirstUpdate) {
|
|
1394
|
+
options.onFirstUpdate(state);
|
|
1395
|
+
}
|
|
1396
|
+
});
|
|
1397
|
+
// Modifiers have the ability to execute arbitrary code before the first
|
|
1398
|
+
// update cycle runs. They will be executed in the same order as the update
|
|
1399
|
+
// cycle. This is useful when a modifier adds some persistent data that
|
|
1400
|
+
// other modifiers need to use, but the modifier is run after the dependent
|
|
1401
|
+
// one.
|
|
1402
|
+
/**
|
|
1403
|
+
*
|
|
1404
|
+
*/
|
|
1405
|
+
function runModifierEffects() {
|
|
1406
|
+
state.orderedModifiers.forEach(({ name, options = {}, effect }) => {
|
|
1407
|
+
if (typeof effect === 'function') {
|
|
1408
|
+
const cleanupFn = effect({ state, name, instance, options });
|
|
1409
|
+
const noopFn = () => { };
|
|
1410
|
+
effectCleanupFns.push(cleanupFn || noopFn);
|
|
1411
|
+
}
|
|
1412
|
+
});
|
|
1413
|
+
}
|
|
1414
|
+
/**
|
|
1415
|
+
*
|
|
1416
|
+
*/
|
|
1417
|
+
function cleanupModifierEffects() {
|
|
1418
|
+
effectCleanupFns.forEach(fn => fn());
|
|
1419
|
+
effectCleanupFns = [];
|
|
1420
|
+
}
|
|
1421
|
+
return instance;
|
|
1422
|
+
};
|
|
1423
|
+
}
|
|
1424
|
+
popperGenerator();
|
|
1425
|
+
|
|
1426
|
+
const passive = { passive: true };
|
|
1427
|
+
/**
|
|
1428
|
+
*
|
|
1429
|
+
*/
|
|
1430
|
+
function effect$2({ state, instance, options }) {
|
|
1431
|
+
const { scroll = true, resize = true } = options;
|
|
1432
|
+
const window = getWindow(state.elements.popper);
|
|
1433
|
+
const scrollParents = [...state.scrollParents.reference, ...state.scrollParents.popper];
|
|
1434
|
+
if (scroll) {
|
|
1435
|
+
scrollParents.forEach(scrollParent => {
|
|
1436
|
+
scrollParent.addEventListener('scroll', instance.update, passive);
|
|
1437
|
+
});
|
|
1438
|
+
}
|
|
1439
|
+
if (resize) {
|
|
1440
|
+
window.addEventListener('resize', instance.update, passive);
|
|
1441
|
+
}
|
|
1442
|
+
return () => {
|
|
1443
|
+
if (scroll) {
|
|
1444
|
+
scrollParents.forEach(scrollParent => {
|
|
1445
|
+
scrollParent.removeEventListener('scroll', instance.update, passive);
|
|
1446
|
+
});
|
|
1447
|
+
}
|
|
1448
|
+
if (resize) {
|
|
1449
|
+
window.removeEventListener('resize', instance.update, passive);
|
|
1450
|
+
}
|
|
1451
|
+
};
|
|
1452
|
+
}
|
|
1453
|
+
const eventListeners = {
|
|
1454
|
+
name: 'eventListeners',
|
|
1455
|
+
enabled: true,
|
|
1456
|
+
phase: 'write',
|
|
1457
|
+
fn: () => { },
|
|
1458
|
+
effect: effect$2,
|
|
1459
|
+
data: {}
|
|
1460
|
+
};
|
|
1461
|
+
|
|
1462
|
+
/**
|
|
1463
|
+
*
|
|
1464
|
+
*/
|
|
1465
|
+
function popperOffsets({ state, name }) {
|
|
1466
|
+
// Offsets are the actual position the popper needs to have to be
|
|
1467
|
+
// properly positioned near its reference element
|
|
1468
|
+
// This is the most basic placement, and will be adjusted by
|
|
1469
|
+
// the modifiers in the next step
|
|
1470
|
+
state.modifiersData[name] = computeOffsets({
|
|
1471
|
+
reference: state.rects.reference,
|
|
1472
|
+
element: state.rects.popper,
|
|
1473
|
+
placement: state.placement
|
|
1474
|
+
});
|
|
1475
|
+
}
|
|
1476
|
+
const popperOffsets$1 = {
|
|
1477
|
+
name: 'popperOffsets',
|
|
1478
|
+
enabled: true,
|
|
1479
|
+
phase: 'read',
|
|
1480
|
+
fn: popperOffsets,
|
|
1481
|
+
data: {}
|
|
1482
|
+
};
|
|
1483
|
+
|
|
1484
|
+
const unsetSides = {
|
|
1485
|
+
top: 'auto',
|
|
1486
|
+
right: 'auto',
|
|
1487
|
+
bottom: 'auto',
|
|
1488
|
+
left: 'auto'
|
|
1489
|
+
};
|
|
1490
|
+
// Round the offsets to the nearest suitable subpixel based on the DPR.
|
|
1491
|
+
// Zooming can change the DPR, but it seems to report a value that will
|
|
1492
|
+
// cleanly divide the values into the appropriate subpixels.
|
|
1493
|
+
/**
|
|
1494
|
+
*
|
|
1495
|
+
*/
|
|
1496
|
+
function roundOffsets({ x, y }) {
|
|
1497
|
+
const win = window;
|
|
1498
|
+
const dpr = win.devicePixelRatio || 1;
|
|
1499
|
+
return {
|
|
1500
|
+
x: Math.round(x * dpr) / dpr || 0,
|
|
1501
|
+
y: Math.round(y * dpr) / dpr || 0
|
|
1502
|
+
};
|
|
1503
|
+
}
|
|
1504
|
+
/**
|
|
1505
|
+
*
|
|
1506
|
+
*/
|
|
1507
|
+
function mapToStyles({ popper, popperRect, placement, offsets, position, gpuAcceleration, adaptive }) {
|
|
1508
|
+
let { x, y } = roundOffsets(offsets);
|
|
1509
|
+
const hasX = offsets.hasOwnProperty('x');
|
|
1510
|
+
const hasY = offsets.hasOwnProperty('y');
|
|
1511
|
+
let sideX = left;
|
|
1512
|
+
let sideY = top;
|
|
1513
|
+
const win = window;
|
|
1514
|
+
if (adaptive) {
|
|
1515
|
+
let offsetParent = getOffsetParent(popper);
|
|
1516
|
+
if (offsetParent === getWindow(popper)) {
|
|
1517
|
+
offsetParent = getDocumentElement(popper);
|
|
1518
|
+
}
|
|
1519
|
+
// $FlowFixMe: force type refinement, we compare offsetParent with window above, but Flow doesn't detect it
|
|
1520
|
+
/* :: offsetParent = (offsetParent: Element); */
|
|
1521
|
+
if (placement === top) {
|
|
1522
|
+
sideY = bottom;
|
|
1523
|
+
y -= offsetParent.clientHeight - popperRect.height;
|
|
1524
|
+
y *= gpuAcceleration ? 1 : -1;
|
|
1525
|
+
}
|
|
1526
|
+
if (placement === left) {
|
|
1527
|
+
sideX = right;
|
|
1528
|
+
x -= offsetParent.clientWidth - popperRect.width;
|
|
1529
|
+
x *= gpuAcceleration ? 1 : -1;
|
|
1530
|
+
}
|
|
1531
|
+
}
|
|
1532
|
+
const commonStyles = Object.assign({ position }, (adaptive && unsetSides));
|
|
1533
|
+
if (gpuAcceleration) {
|
|
1534
|
+
return Object.assign(Object.assign({}, commonStyles), { [sideY]: hasY ? '0' : '', [sideX]: hasX ? '0' : '',
|
|
1535
|
+
// Layer acceleration can disable subpixel rendering which causes slightly
|
|
1536
|
+
// blurry text on low PPI displays, so we want to use 2D transforms
|
|
1537
|
+
// instead
|
|
1538
|
+
transform: (win.devicePixelRatio || 1) < 2 ? `translate(${x}px, ${y}px)` : `translate3d(${x}px, ${y}px, 0)` });
|
|
1539
|
+
}
|
|
1540
|
+
return Object.assign(Object.assign({}, commonStyles), { [sideY]: hasY ? `${y}px` : '', [sideX]: hasX ? `${x}px` : '', transform: '' });
|
|
1541
|
+
}
|
|
1542
|
+
/**
|
|
1543
|
+
*
|
|
1544
|
+
*/
|
|
1545
|
+
function computeStyles({ state, options }) {
|
|
1546
|
+
const { gpuAcceleration = true, adaptive = true } = options;
|
|
1547
|
+
const commonStyles = {
|
|
1548
|
+
placement: getBasePlacement(state.placement),
|
|
1549
|
+
popper: state.elements.popper,
|
|
1550
|
+
popperRect: state.rects.popper,
|
|
1551
|
+
gpuAcceleration
|
|
1552
|
+
};
|
|
1553
|
+
if (state.modifiersData.popperOffsets != null) {
|
|
1554
|
+
state.styles.popper = Object.assign(Object.assign({}, state.styles.popper), mapToStyles(Object.assign(Object.assign({}, commonStyles), { offsets: state.modifiersData.popperOffsets, position: state.options.strategy, adaptive })));
|
|
1555
|
+
}
|
|
1556
|
+
if (state.modifiersData.arrow != null) {
|
|
1557
|
+
state.styles.arrow = Object.assign(Object.assign({}, state.styles.arrow), mapToStyles(Object.assign(Object.assign({}, commonStyles), { offsets: state.modifiersData.arrow, position: 'absolute', adaptive: false })));
|
|
1558
|
+
}
|
|
1559
|
+
state.attributes.popper = Object.assign(Object.assign({}, state.attributes.popper), { 'data-popper-placement': state.placement });
|
|
1560
|
+
}
|
|
1561
|
+
const computeStyles$1 = {
|
|
1562
|
+
name: 'computeStyles',
|
|
1563
|
+
enabled: true,
|
|
1564
|
+
phase: 'beforeWrite',
|
|
1565
|
+
fn: computeStyles,
|
|
1566
|
+
data: {}
|
|
1567
|
+
};
|
|
1568
|
+
|
|
1569
|
+
// This modifier takes the styles prepared by the `computeStyles` modifier
|
|
1570
|
+
// and applies them to the HTMLElements such as popper and arrow
|
|
1571
|
+
/**
|
|
1572
|
+
*
|
|
1573
|
+
*/
|
|
1574
|
+
function applyStyles({ state }) {
|
|
1575
|
+
Object.keys(state.elements).forEach(name => {
|
|
1576
|
+
const style = state.styles[name] || {};
|
|
1577
|
+
const attributes = state.attributes[name] || {};
|
|
1578
|
+
const element = state.elements[name];
|
|
1579
|
+
// arrow is optional + virtual elements
|
|
1580
|
+
if (!isHTMLElement(element) || !getNodeName(element)) {
|
|
1581
|
+
return;
|
|
1582
|
+
}
|
|
1583
|
+
// Flow doesn't support to extend this property, but it's the most
|
|
1584
|
+
// effective way to apply styles to an HTMLElement
|
|
1585
|
+
// $FlowFixMe
|
|
1586
|
+
Object.assign(element.style, style);
|
|
1587
|
+
Object.keys(attributes).forEach(name => {
|
|
1588
|
+
const value = attributes[name];
|
|
1589
|
+
if (value === false) {
|
|
1590
|
+
element.removeAttribute(name);
|
|
1591
|
+
}
|
|
1592
|
+
else {
|
|
1593
|
+
element.setAttribute(name, value === true ? '' : value);
|
|
1594
|
+
}
|
|
1595
|
+
});
|
|
1596
|
+
});
|
|
1597
|
+
}
|
|
1598
|
+
/**
|
|
1599
|
+
*
|
|
1600
|
+
*/
|
|
1601
|
+
function effect$1({ state }) {
|
|
1602
|
+
const initialStyles = {
|
|
1603
|
+
popper: {
|
|
1604
|
+
position: state.options.strategy,
|
|
1605
|
+
left: '0',
|
|
1606
|
+
top: '0',
|
|
1607
|
+
margin: '0'
|
|
1608
|
+
},
|
|
1609
|
+
arrow: {
|
|
1610
|
+
position: 'absolute'
|
|
1611
|
+
},
|
|
1612
|
+
reference: {}
|
|
1613
|
+
};
|
|
1614
|
+
Object.assign(state.elements.popper.style, initialStyles.popper);
|
|
1615
|
+
if (state.elements.arrow) {
|
|
1616
|
+
Object.assign(state.elements.arrow.style, initialStyles.arrow);
|
|
1617
|
+
}
|
|
1618
|
+
return () => {
|
|
1619
|
+
Object.keys(state.elements).forEach(name => {
|
|
1620
|
+
const element = state.elements[name];
|
|
1621
|
+
const attributes = state.attributes[name] || {};
|
|
1622
|
+
const styleProperties = Object.keys(state.styles.hasOwnProperty(name) ? state.styles[name] : initialStyles[name]);
|
|
1623
|
+
// Set all values to an empty string to unset them
|
|
1624
|
+
const style = styleProperties.reduce((style, property) => {
|
|
1625
|
+
style[property] = '';
|
|
1626
|
+
return style;
|
|
1627
|
+
}, {});
|
|
1628
|
+
// arrow is optional + virtual elements
|
|
1629
|
+
if (!isHTMLElement(element) || !getNodeName(element)) {
|
|
1630
|
+
return;
|
|
1631
|
+
}
|
|
1632
|
+
// Flow doesn't support to extend this property, but it's the most
|
|
1633
|
+
// effective way to apply styles to an HTMLElement
|
|
1634
|
+
// $FlowFixMe
|
|
1635
|
+
Object.assign(element.style, style);
|
|
1636
|
+
Object.keys(attributes).forEach(attribute => {
|
|
1637
|
+
element.removeAttribute(attribute);
|
|
1638
|
+
});
|
|
1639
|
+
});
|
|
1640
|
+
};
|
|
1641
|
+
}
|
|
1642
|
+
const applyStyles$1 = {
|
|
1643
|
+
name: 'applyStyles',
|
|
1644
|
+
enabled: true,
|
|
1645
|
+
phase: 'write',
|
|
1646
|
+
fn: applyStyles,
|
|
1647
|
+
effect: effect$1,
|
|
1648
|
+
requires: ['computeStyles']
|
|
1649
|
+
};
|
|
1650
|
+
|
|
1651
|
+
/**
|
|
1652
|
+
* @param placement
|
|
1653
|
+
* @param rects
|
|
1654
|
+
* @param offset
|
|
1655
|
+
*/
|
|
1656
|
+
function distanceAndSkiddingToXY(placement, rects, offset) {
|
|
1657
|
+
const basePlacement = getBasePlacement(placement);
|
|
1658
|
+
const invertDistance = [left, top].indexOf(basePlacement) >= 0 ? -1 : 1;
|
|
1659
|
+
let [skidding, distance] = typeof offset === 'function'
|
|
1660
|
+
? offset(Object.assign(Object.assign({}, rects), { placement }))
|
|
1661
|
+
: offset;
|
|
1662
|
+
skidding = skidding || 0;
|
|
1663
|
+
distance = (distance || 0) * invertDistance;
|
|
1664
|
+
return [left, right].indexOf(basePlacement) >= 0 ? { x: distance, y: skidding } : { x: skidding, y: distance };
|
|
1665
|
+
}
|
|
1666
|
+
/**
|
|
1667
|
+
*
|
|
1668
|
+
*/
|
|
1669
|
+
function offset({ state, options, name }) {
|
|
1670
|
+
const { offset = [0, 0] } = options;
|
|
1671
|
+
const data = placements.reduce((acc, placement) => {
|
|
1672
|
+
acc[placement] = distanceAndSkiddingToXY(placement, state.rects, offset);
|
|
1673
|
+
return acc;
|
|
1674
|
+
}, {});
|
|
1675
|
+
const { x, y } = data[state.placement];
|
|
1676
|
+
if (state.modifiersData.popperOffsets != null) {
|
|
1677
|
+
state.modifiersData.popperOffsets.x += x;
|
|
1678
|
+
state.modifiersData.popperOffsets.y += y;
|
|
1679
|
+
}
|
|
1680
|
+
state.modifiersData[name] = data;
|
|
1681
|
+
}
|
|
1682
|
+
const offset$1 = {
|
|
1683
|
+
name: 'offset',
|
|
1684
|
+
enabled: true,
|
|
1685
|
+
phase: 'main',
|
|
1686
|
+
requires: ['popperOffsets'],
|
|
1687
|
+
fn: offset
|
|
1688
|
+
};
|
|
1689
|
+
|
|
1690
|
+
const hash$2 = { left: 'right', right: 'left', bottom: 'top', top: 'bottom' };
|
|
1691
|
+
/**
|
|
1692
|
+
* @param placement
|
|
1693
|
+
*/
|
|
1694
|
+
function getOppositePlacement$1(placement) {
|
|
1695
|
+
return placement.replace(/left|right|bottom|top/g, matched => hash$2[matched]);
|
|
1696
|
+
}
|
|
1697
|
+
|
|
1698
|
+
const hash$1 = { start: 'end', end: 'start' };
|
|
1699
|
+
/**
|
|
1700
|
+
* @param placement
|
|
1701
|
+
*/
|
|
1702
|
+
function getOppositeVariationPlacement(placement) {
|
|
1703
|
+
return placement.replace(/start|end/g, matched => hash$1[matched]);
|
|
1704
|
+
}
|
|
1705
|
+
|
|
1706
|
+
/* :: type OverflowsMap = { [ComputedPlacement]: number }; */
|
|
1707
|
+
/* ;; type OverflowsMap = { [key in ComputedPlacement]: number }; */
|
|
1708
|
+
/**
|
|
1709
|
+
* @param state
|
|
1710
|
+
* @param options
|
|
1711
|
+
*/
|
|
1712
|
+
function computeAutoPlacement(state, options = {}) {
|
|
1713
|
+
const { placement, boundary, rootBoundary, padding, flipVariations, allowedAutoPlacements = placements } = options;
|
|
1714
|
+
const variation = getVariation(placement);
|
|
1715
|
+
const placements$1 = variation
|
|
1716
|
+
? flipVariations
|
|
1717
|
+
? variationPlacements
|
|
1718
|
+
: variationPlacements.filter(placement => getVariation(placement) === variation)
|
|
1719
|
+
: basePlacements;
|
|
1720
|
+
// $FlowFixMe
|
|
1721
|
+
let allowedPlacements = placements$1.filter(placement => allowedAutoPlacements.indexOf(placement) >= 0);
|
|
1722
|
+
if (allowedPlacements.length === 0) {
|
|
1723
|
+
allowedPlacements = placements$1;
|
|
1724
|
+
}
|
|
1725
|
+
// $FlowFixMe: Flow seems to have problems with two array unions...
|
|
1726
|
+
const overflows = allowedPlacements.reduce((acc, placement) => {
|
|
1727
|
+
acc[placement] = detectOverflow(state, {
|
|
1728
|
+
placement,
|
|
1729
|
+
boundary,
|
|
1730
|
+
rootBoundary,
|
|
1731
|
+
padding
|
|
1732
|
+
})[getBasePlacement(placement)];
|
|
1733
|
+
return acc;
|
|
1734
|
+
}, {});
|
|
1735
|
+
return Object.keys(overflows).sort((a, b) => overflows[a] - overflows[b]);
|
|
1736
|
+
}
|
|
1737
|
+
|
|
1738
|
+
/**
|
|
1739
|
+
* @param placement
|
|
1740
|
+
*/
|
|
1741
|
+
function getExpandedFallbackPlacements(placement) {
|
|
1742
|
+
if (getBasePlacement(placement) === auto) {
|
|
1743
|
+
return [];
|
|
1744
|
+
}
|
|
1745
|
+
const oppositePlacement = getOppositePlacement$1(placement);
|
|
1746
|
+
return [
|
|
1747
|
+
getOppositeVariationPlacement(placement),
|
|
1748
|
+
oppositePlacement,
|
|
1749
|
+
getOppositeVariationPlacement(oppositePlacement)
|
|
1750
|
+
];
|
|
1751
|
+
}
|
|
1752
|
+
/**
|
|
1753
|
+
*
|
|
1754
|
+
*/
|
|
1755
|
+
function flip({ state, options, name }) {
|
|
1756
|
+
if (state.modifiersData[name]._skip) {
|
|
1757
|
+
return;
|
|
1758
|
+
}
|
|
1759
|
+
const { mainAxis: checkMainAxis = true, altAxis: checkAltAxis = true, fallbackPlacements: specifiedFallbackPlacements, padding, boundary, rootBoundary, altBoundary, flipVariations = true, allowedAutoPlacements } = options;
|
|
1760
|
+
const preferredPlacement = state.options.placement;
|
|
1761
|
+
const basePlacement = getBasePlacement(preferredPlacement);
|
|
1762
|
+
const isBasePlacement = basePlacement === preferredPlacement;
|
|
1763
|
+
const fallbackPlacements = specifiedFallbackPlacements ||
|
|
1764
|
+
(isBasePlacement || !flipVariations
|
|
1765
|
+
? [getOppositePlacement$1(preferredPlacement)]
|
|
1766
|
+
: getExpandedFallbackPlacements(preferredPlacement));
|
|
1767
|
+
const placements = [preferredPlacement, ...fallbackPlacements].reduce((acc, placement) => acc.concat(getBasePlacement(placement) === auto
|
|
1768
|
+
? computeAutoPlacement(state, {
|
|
1769
|
+
placement,
|
|
1770
|
+
boundary,
|
|
1771
|
+
rootBoundary,
|
|
1772
|
+
padding,
|
|
1773
|
+
flipVariations,
|
|
1774
|
+
allowedAutoPlacements
|
|
1775
|
+
})
|
|
1776
|
+
: placement), []);
|
|
1777
|
+
const referenceRect = state.rects.reference;
|
|
1778
|
+
const popperRect = state.rects.popper;
|
|
1779
|
+
const checksMap = new Map();
|
|
1780
|
+
let makeFallbackChecks = true;
|
|
1781
|
+
let firstFittingPlacement = placements[0];
|
|
1782
|
+
for (let i = 0; i < placements.length; i++) {
|
|
1783
|
+
const placement = placements[i];
|
|
1784
|
+
const basePlacement = getBasePlacement(placement);
|
|
1785
|
+
const isStartVariation = getVariation(placement) === start;
|
|
1786
|
+
const isVertical = [top, bottom].indexOf(basePlacement) >= 0;
|
|
1787
|
+
const len = isVertical ? 'width' : 'height';
|
|
1788
|
+
const overflow = detectOverflow(state, {
|
|
1789
|
+
placement,
|
|
1790
|
+
boundary,
|
|
1791
|
+
rootBoundary,
|
|
1792
|
+
altBoundary,
|
|
1793
|
+
padding
|
|
1794
|
+
});
|
|
1795
|
+
let mainVariationSide = isVertical ? (isStartVariation ? right : left) : isStartVariation ? bottom : top;
|
|
1796
|
+
if (referenceRect[len] > popperRect[len]) {
|
|
1797
|
+
mainVariationSide = getOppositePlacement$1(mainVariationSide);
|
|
1798
|
+
}
|
|
1799
|
+
const altVariationSide = getOppositePlacement$1(mainVariationSide);
|
|
1800
|
+
const checks = [];
|
|
1801
|
+
if (checkMainAxis) {
|
|
1802
|
+
checks.push(overflow[basePlacement] <= 0);
|
|
1803
|
+
}
|
|
1804
|
+
if (checkAltAxis) {
|
|
1805
|
+
checks.push(overflow[mainVariationSide] <= 0, overflow[altVariationSide] <= 0);
|
|
1806
|
+
}
|
|
1807
|
+
if (checks.every(check => check)) {
|
|
1808
|
+
firstFittingPlacement = placement;
|
|
1809
|
+
makeFallbackChecks = false;
|
|
1810
|
+
break;
|
|
1811
|
+
}
|
|
1812
|
+
checksMap.set(placement, checks);
|
|
1813
|
+
}
|
|
1814
|
+
if (makeFallbackChecks) {
|
|
1815
|
+
// `2` may be desired in some cases – research later
|
|
1816
|
+
const numberOfChecks = flipVariations ? 3 : 1;
|
|
1817
|
+
for (let i = numberOfChecks; i > 0; i--) {
|
|
1818
|
+
const fittingPlacement = placements.find(placement => {
|
|
1819
|
+
const checks = checksMap.get(placement);
|
|
1820
|
+
if (checks) {
|
|
1821
|
+
return checks.slice(0, i).every(check => check);
|
|
1822
|
+
}
|
|
1823
|
+
});
|
|
1824
|
+
if (fittingPlacement) {
|
|
1825
|
+
firstFittingPlacement = fittingPlacement;
|
|
1826
|
+
break;
|
|
1827
|
+
}
|
|
1828
|
+
}
|
|
1829
|
+
}
|
|
1830
|
+
if (state.placement !== firstFittingPlacement) {
|
|
1831
|
+
state.modifiersData[name]._skip = true;
|
|
1832
|
+
state.placement = firstFittingPlacement;
|
|
1833
|
+
state.reset = true;
|
|
1834
|
+
}
|
|
1835
|
+
}
|
|
1836
|
+
const flip$1 = {
|
|
1837
|
+
name: 'flip',
|
|
1838
|
+
enabled: true,
|
|
1839
|
+
phase: 'main',
|
|
1840
|
+
fn: flip,
|
|
1841
|
+
requiresIfExists: ['offset'],
|
|
1842
|
+
data: { _skip: false }
|
|
1843
|
+
};
|
|
1844
|
+
|
|
1845
|
+
// @ts-nocheck
|
|
1846
|
+
/**
|
|
1847
|
+
* @param axis
|
|
1848
|
+
*/
|
|
1849
|
+
function getAltAxis(axis) {
|
|
1850
|
+
return axis === 'x' ? 'y' : 'x';
|
|
1851
|
+
}
|
|
1852
|
+
|
|
1853
|
+
// @ts-nocheck
|
|
1854
|
+
/**
|
|
1855
|
+
* @param min
|
|
1856
|
+
* @param value
|
|
1857
|
+
* @param max
|
|
1858
|
+
*/
|
|
1859
|
+
function within(min, value, max) {
|
|
1860
|
+
return Math.max(min, Math.min(value, max));
|
|
1861
|
+
}
|
|
1862
|
+
|
|
1863
|
+
// @ts-nocheck
|
|
1864
|
+
/**
|
|
1865
|
+
*
|
|
1866
|
+
*/
|
|
1867
|
+
function preventOverflow({ state, options, name }) {
|
|
1868
|
+
const { mainAxis: checkMainAxis = true, altAxis: checkAltAxis = false, boundary, rootBoundary, altBoundary, padding, tether = true, tetherOffset = 0 } = options;
|
|
1869
|
+
const overflow = detectOverflow(state, {
|
|
1870
|
+
boundary,
|
|
1871
|
+
rootBoundary,
|
|
1872
|
+
padding,
|
|
1873
|
+
altBoundary
|
|
1874
|
+
});
|
|
1875
|
+
const basePlacement = getBasePlacement(state.placement);
|
|
1876
|
+
const variation = getVariation(state.placement);
|
|
1877
|
+
const isBasePlacement = !variation;
|
|
1878
|
+
const mainAxis = getMainAxisFromPlacement(basePlacement);
|
|
1879
|
+
const altAxis = getAltAxis(mainAxis);
|
|
1880
|
+
const popperOffsets = state.modifiersData.popperOffsets;
|
|
1881
|
+
const referenceRect = state.rects.reference;
|
|
1882
|
+
const popperRect = state.rects.popper;
|
|
1883
|
+
const tetherOffsetValue = typeof tetherOffset === 'function'
|
|
1884
|
+
? tetherOffset(Object.assign(Object.assign({}, state.rects), { placement: state.placement }))
|
|
1885
|
+
: tetherOffset;
|
|
1886
|
+
const data = { x: 0, y: 0 };
|
|
1887
|
+
if (!popperOffsets) {
|
|
1888
|
+
return;
|
|
1889
|
+
}
|
|
1890
|
+
if (checkMainAxis) {
|
|
1891
|
+
const mainSide = mainAxis === 'y' ? top : left;
|
|
1892
|
+
const altSide = mainAxis === 'y' ? bottom : right;
|
|
1893
|
+
const len = mainAxis === 'y' ? 'height' : 'width';
|
|
1894
|
+
const offset = popperOffsets[mainAxis];
|
|
1895
|
+
const min = popperOffsets[mainAxis] + overflow[mainSide];
|
|
1896
|
+
const max = popperOffsets[mainAxis] - overflow[altSide];
|
|
1897
|
+
const additive = tether ? -popperRect[len] / 2 : 0;
|
|
1898
|
+
const minLen = variation === start ? referenceRect[len] : popperRect[len];
|
|
1899
|
+
const maxLen = variation === start ? -popperRect[len] : -referenceRect[len];
|
|
1900
|
+
// We need to include the arrow in the calculation so the arrow doesn't go
|
|
1901
|
+
// outside the reference bounds
|
|
1902
|
+
const arrowElement = state.elements.arrow;
|
|
1903
|
+
const arrowRect = tether && arrowElement ? getLayoutRect(arrowElement) : { width: 0, height: 0 };
|
|
1904
|
+
const arrowPaddingObject = state.modifiersData['arrow#persistent']
|
|
1905
|
+
? state.modifiersData['arrow#persistent'].padding
|
|
1906
|
+
: getFreshSideObject();
|
|
1907
|
+
const arrowPaddingMin = arrowPaddingObject[mainSide];
|
|
1908
|
+
const arrowPaddingMax = arrowPaddingObject[altSide];
|
|
1909
|
+
// If the reference length is smaller than the arrow length, we don't want
|
|
1910
|
+
// to include its full size in the calculation. If the reference is small
|
|
1911
|
+
// and near the edge of a boundary, the popper can overflow even if the
|
|
1912
|
+
// reference is not overflowing as well (e.g. virtual elements with no
|
|
1913
|
+
// width or height)
|
|
1914
|
+
const arrowLen = within(0, referenceRect[len], arrowRect[len]);
|
|
1915
|
+
const minOffset = isBasePlacement
|
|
1916
|
+
? referenceRect[len] / 2 - additive - arrowLen - arrowPaddingMin - tetherOffsetValue
|
|
1917
|
+
: minLen - arrowLen - arrowPaddingMin - tetherOffsetValue;
|
|
1918
|
+
const maxOffset = isBasePlacement
|
|
1919
|
+
? -referenceRect[len] / 2 + additive + arrowLen + arrowPaddingMax + tetherOffsetValue
|
|
1920
|
+
: maxLen + arrowLen + arrowPaddingMax + tetherOffsetValue;
|
|
1921
|
+
const arrowOffsetParent = state.elements.arrow && getOffsetParent(state.elements.arrow);
|
|
1922
|
+
const clientOffset = arrowOffsetParent
|
|
1923
|
+
? mainAxis === 'y'
|
|
1924
|
+
? arrowOffsetParent.clientTop || 0
|
|
1925
|
+
: arrowOffsetParent.clientLeft || 0
|
|
1926
|
+
: 0;
|
|
1927
|
+
const offsetModifierValue = state.modifiersData.offset ? state.modifiersData.offset[state.placement][mainAxis] : 0;
|
|
1928
|
+
const tetherMin = popperOffsets[mainAxis] + minOffset - offsetModifierValue - clientOffset;
|
|
1929
|
+
const tetherMax = popperOffsets[mainAxis] + maxOffset - offsetModifierValue;
|
|
1930
|
+
const preventedOffset = within(tether ? Math.min(min, tetherMin) : min, offset, tether ? Math.max(max, tetherMax) : max);
|
|
1931
|
+
popperOffsets[mainAxis] = preventedOffset;
|
|
1932
|
+
data[mainAxis] = preventedOffset - offset;
|
|
1933
|
+
}
|
|
1934
|
+
if (checkAltAxis) {
|
|
1935
|
+
const mainSide = mainAxis === 'x' ? top : left;
|
|
1936
|
+
const altSide = mainAxis === 'x' ? bottom : right;
|
|
1937
|
+
const offset = popperOffsets[altAxis];
|
|
1938
|
+
const min = offset + overflow[mainSide];
|
|
1939
|
+
const max = offset - overflow[altSide];
|
|
1940
|
+
const preventedOffset = within(min, offset, max);
|
|
1941
|
+
popperOffsets[altAxis] = preventedOffset;
|
|
1942
|
+
data[altAxis] = preventedOffset - offset;
|
|
1943
|
+
}
|
|
1944
|
+
state.modifiersData[name] = data;
|
|
1945
|
+
}
|
|
1946
|
+
const preventOverflow$1 = {
|
|
1947
|
+
name: 'preventOverflow',
|
|
1948
|
+
enabled: true,
|
|
1949
|
+
phase: 'main',
|
|
1950
|
+
fn: preventOverflow,
|
|
1951
|
+
requiresIfExists: ['offset']
|
|
1952
|
+
};
|
|
1953
|
+
|
|
1954
|
+
/**
|
|
1955
|
+
*
|
|
1956
|
+
*/
|
|
1957
|
+
function arrow({ state, name }) {
|
|
1958
|
+
const arrowElement = state.elements.arrow;
|
|
1959
|
+
const popperOffsets = state.modifiersData.popperOffsets;
|
|
1960
|
+
const basePlacement = getBasePlacement(state.placement);
|
|
1961
|
+
const axis = getMainAxisFromPlacement(basePlacement);
|
|
1962
|
+
const isVertical = [left, right].indexOf(basePlacement) >= 0;
|
|
1963
|
+
const len = isVertical ? 'height' : 'width';
|
|
1964
|
+
if (!arrowElement || !popperOffsets) {
|
|
1965
|
+
return;
|
|
1966
|
+
}
|
|
1967
|
+
const paddingObject = state.modifiersData[`${name}#persistent`].padding;
|
|
1968
|
+
const arrowRect = getLayoutRect(arrowElement);
|
|
1969
|
+
const minProp = axis === 'y' ? top : left;
|
|
1970
|
+
const maxProp = axis === 'y' ? bottom : right;
|
|
1971
|
+
const endDiff = state.rects.reference[len] + state.rects.reference[axis] - popperOffsets[axis] - state.rects.popper[len];
|
|
1972
|
+
const startDiff = popperOffsets[axis] - state.rects.reference[axis];
|
|
1973
|
+
const arrowOffsetParent = getOffsetParent(arrowElement);
|
|
1974
|
+
const clientSize = arrowOffsetParent
|
|
1975
|
+
? axis === 'y'
|
|
1976
|
+
? arrowOffsetParent.clientHeight || 0
|
|
1977
|
+
: arrowOffsetParent.clientWidth || 0
|
|
1978
|
+
: 0;
|
|
1979
|
+
const centerToReference = endDiff / 2 - startDiff / 2;
|
|
1980
|
+
// Make sure the arrow doesn't overflow the popper if the center point is
|
|
1981
|
+
// outside of the popper bounds
|
|
1982
|
+
const min = paddingObject[minProp];
|
|
1983
|
+
const max = clientSize - arrowRect[len] - paddingObject[maxProp];
|
|
1984
|
+
const center = clientSize / 2 - arrowRect[len] / 2 + centerToReference;
|
|
1985
|
+
const offset = within(min, center, max);
|
|
1986
|
+
// Prevents breaking syntax highlighting...
|
|
1987
|
+
const axisProp = axis;
|
|
1988
|
+
state.modifiersData[name] = {
|
|
1989
|
+
[axisProp]: offset,
|
|
1990
|
+
centerOffset: offset - center
|
|
1991
|
+
};
|
|
1992
|
+
}
|
|
1993
|
+
/**
|
|
1994
|
+
*
|
|
1995
|
+
*/
|
|
1996
|
+
function effect({ state, options, name }) {
|
|
1997
|
+
let { element: arrowElement = '[data-popper-arrow]', padding = 0 } = options;
|
|
1998
|
+
if (arrowElement == null) {
|
|
1999
|
+
return;
|
|
2000
|
+
}
|
|
2001
|
+
// CSS selector
|
|
2002
|
+
if (typeof arrowElement === 'string') {
|
|
2003
|
+
arrowElement = state.elements.popper.querySelector(arrowElement);
|
|
2004
|
+
if (!arrowElement) {
|
|
2005
|
+
return;
|
|
2006
|
+
}
|
|
2007
|
+
}
|
|
2008
|
+
if (!contains(state.elements.popper, arrowElement)) {
|
|
2009
|
+
return;
|
|
2010
|
+
}
|
|
2011
|
+
state.elements.arrow = arrowElement;
|
|
2012
|
+
state.modifiersData[`${name}#persistent`] = {
|
|
2013
|
+
padding: mergePaddingObject(typeof padding !== 'number' ? padding : expandToHashMap(padding, basePlacements))
|
|
2014
|
+
};
|
|
2015
|
+
}
|
|
2016
|
+
const arrow$1 = {
|
|
2017
|
+
name: 'arrow',
|
|
2018
|
+
enabled: true,
|
|
2019
|
+
phase: 'main',
|
|
2020
|
+
fn: arrow,
|
|
2021
|
+
effect,
|
|
2022
|
+
requires: ['popperOffsets'],
|
|
2023
|
+
requiresIfExists: ['preventOverflow']
|
|
2024
|
+
};
|
|
2025
|
+
|
|
2026
|
+
/**
|
|
2027
|
+
* @param overflow
|
|
2028
|
+
* @param rect
|
|
2029
|
+
* @param preventedOffsets
|
|
2030
|
+
*/
|
|
2031
|
+
function getSideOffsets(overflow, rect, preventedOffsets = { x: 0, y: 0 }) {
|
|
2032
|
+
return {
|
|
2033
|
+
top: overflow.top - rect.height - preventedOffsets.y,
|
|
2034
|
+
right: overflow.right - rect.width + preventedOffsets.x,
|
|
2035
|
+
bottom: overflow.bottom - rect.height + preventedOffsets.y,
|
|
2036
|
+
left: overflow.left - rect.width - preventedOffsets.x
|
|
2037
|
+
};
|
|
2038
|
+
}
|
|
2039
|
+
/**
|
|
2040
|
+
* @param overflow
|
|
2041
|
+
*/
|
|
2042
|
+
function isAnySideFullyClipped(overflow) {
|
|
2043
|
+
return [top, right, bottom, left].some(side => overflow[side] >= 0);
|
|
2044
|
+
}
|
|
2045
|
+
/**
|
|
2046
|
+
*
|
|
2047
|
+
*/
|
|
2048
|
+
function hide({ state, name }) {
|
|
2049
|
+
const referenceRect = state.rects.reference;
|
|
2050
|
+
const popperRect = state.rects.popper;
|
|
2051
|
+
const preventedOffsets = state.modifiersData.preventOverflow;
|
|
2052
|
+
const referenceOverflow = detectOverflow(state, {
|
|
2053
|
+
elementContext: 'reference'
|
|
2054
|
+
});
|
|
2055
|
+
const popperAltOverflow = detectOverflow(state, {
|
|
2056
|
+
altBoundary: true
|
|
2057
|
+
});
|
|
2058
|
+
const referenceClippingOffsets = getSideOffsets(referenceOverflow, referenceRect);
|
|
2059
|
+
const popperEscapeOffsets = getSideOffsets(popperAltOverflow, popperRect, preventedOffsets);
|
|
2060
|
+
const isReferenceHidden = isAnySideFullyClipped(referenceClippingOffsets);
|
|
2061
|
+
const hasPopperEscaped = isAnySideFullyClipped(popperEscapeOffsets);
|
|
2062
|
+
state.modifiersData[name] = {
|
|
2063
|
+
referenceClippingOffsets,
|
|
2064
|
+
popperEscapeOffsets,
|
|
2065
|
+
isReferenceHidden,
|
|
2066
|
+
hasPopperEscaped
|
|
2067
|
+
};
|
|
2068
|
+
state.attributes.popper = Object.assign(Object.assign({}, state.attributes.popper), { 'data-popper-reference-hidden': isReferenceHidden, 'data-popper-escaped': hasPopperEscaped });
|
|
2069
|
+
}
|
|
2070
|
+
const hide$1 = {
|
|
2071
|
+
name: 'hide',
|
|
2072
|
+
enabled: true,
|
|
2073
|
+
phase: 'main',
|
|
2074
|
+
requiresIfExists: ['preventOverflow'],
|
|
2075
|
+
fn: hide
|
|
2076
|
+
};
|
|
2077
|
+
|
|
2078
|
+
// @ts-nocheck
|
|
2079
|
+
const defaultModifiers = [
|
|
2080
|
+
eventListeners,
|
|
2081
|
+
popperOffsets$1,
|
|
2082
|
+
computeStyles$1,
|
|
2083
|
+
applyStyles$1,
|
|
2084
|
+
offset$1,
|
|
2085
|
+
flip$1,
|
|
2086
|
+
preventOverflow$1,
|
|
2087
|
+
arrow$1,
|
|
2088
|
+
hide$1
|
|
2089
|
+
];
|
|
2090
|
+
const createPopper = popperGenerator({ defaultModifiers });
|
|
2091
|
+
|
|
2092
|
+
/**
|
|
2093
|
+
* Small wrapper around `useLayoutEffect` to get rid of the warning on SSR envs
|
|
2094
|
+
*/
|
|
2095
|
+
const useIsomorphicLayoutEffect = canUseDOM ? React.useLayoutEffect : React.useEffect;
|
|
2096
|
+
|
|
2097
|
+
/* eslint-disable @typescript-eslint/consistent-type-definitions */
|
|
2098
|
+
const isEqual = (a, b) => JSON.stringify(a) === JSON.stringify(b);
|
|
2099
|
+
/**
|
|
2100
|
+
* Simple ponyfill for Object.fromEntries
|
|
2101
|
+
*/
|
|
2102
|
+
const fromEntries = (entries) => entries.reduce((acc, [key, value]) => {
|
|
2103
|
+
acc[key] = value;
|
|
2104
|
+
return acc;
|
|
2105
|
+
}, {});
|
|
2106
|
+
const EMPTY_MODIFIERS = [];
|
|
2107
|
+
const usePopper = (referenceElement, popperElement, options = {}) => {
|
|
2108
|
+
const prevOptions = React.useRef(null);
|
|
2109
|
+
const optionsWithDefaults = {
|
|
2110
|
+
onFirstUpdate: options.onFirstUpdate,
|
|
2111
|
+
placement: options.placement || 'bottom',
|
|
2112
|
+
strategy: options.strategy || 'absolute',
|
|
2113
|
+
modifiers: options.modifiers || EMPTY_MODIFIERS
|
|
2114
|
+
};
|
|
2115
|
+
const [state, setState] = React.useState({
|
|
2116
|
+
styles: {
|
|
2117
|
+
popper: {
|
|
2118
|
+
position: optionsWithDefaults.strategy,
|
|
2119
|
+
left: '0',
|
|
2120
|
+
top: '0'
|
|
2121
|
+
}
|
|
2122
|
+
},
|
|
2123
|
+
attributes: {}
|
|
2124
|
+
});
|
|
2125
|
+
const updateStateModifier = React.useMemo(() => ({
|
|
2126
|
+
name: 'updateState',
|
|
2127
|
+
enabled: true,
|
|
2128
|
+
phase: 'write',
|
|
2129
|
+
// eslint-disable-next-line no-shadow
|
|
2130
|
+
fn: ({ state }) => {
|
|
2131
|
+
const elements = Object.keys(state.elements);
|
|
2132
|
+
setState({
|
|
2133
|
+
styles: fromEntries(elements.map(element => [element, state.styles[element] || {}])),
|
|
2134
|
+
attributes: fromEntries(elements.map(element => [element, state.attributes[element]]))
|
|
2135
|
+
});
|
|
2136
|
+
},
|
|
2137
|
+
requires: ['computeStyles']
|
|
2138
|
+
}), []);
|
|
2139
|
+
const popperOptions = React.useMemo(() => {
|
|
2140
|
+
const newOptions = {
|
|
2141
|
+
onFirstUpdate: optionsWithDefaults.onFirstUpdate,
|
|
2142
|
+
placement: optionsWithDefaults.placement,
|
|
2143
|
+
strategy: optionsWithDefaults.strategy,
|
|
2144
|
+
modifiers: [...optionsWithDefaults.modifiers, updateStateModifier, { name: 'applyStyles', enabled: false }]
|
|
2145
|
+
};
|
|
2146
|
+
if (isEqual(prevOptions.current, newOptions)) {
|
|
2147
|
+
return prevOptions.current || newOptions;
|
|
2148
|
+
}
|
|
2149
|
+
else {
|
|
2150
|
+
prevOptions.current = newOptions;
|
|
2151
|
+
return newOptions;
|
|
2152
|
+
}
|
|
2153
|
+
}, [
|
|
2154
|
+
optionsWithDefaults.onFirstUpdate,
|
|
2155
|
+
optionsWithDefaults.placement,
|
|
2156
|
+
optionsWithDefaults.strategy,
|
|
2157
|
+
optionsWithDefaults.modifiers,
|
|
2158
|
+
updateStateModifier
|
|
2159
|
+
]);
|
|
2160
|
+
const popperInstanceRef = React.useRef();
|
|
2161
|
+
useIsomorphicLayoutEffect(() => {
|
|
2162
|
+
if (popperInstanceRef && popperInstanceRef.current) {
|
|
2163
|
+
popperInstanceRef.current.setOptions(popperOptions);
|
|
2164
|
+
}
|
|
2165
|
+
}, [popperOptions]);
|
|
2166
|
+
useIsomorphicLayoutEffect(() => {
|
|
2167
|
+
if (referenceElement == null || popperElement == null) {
|
|
2168
|
+
return;
|
|
2169
|
+
}
|
|
2170
|
+
const createPopper$1 = options.createPopper || createPopper;
|
|
2171
|
+
const popperInstance = createPopper$1(referenceElement, popperElement, popperOptions);
|
|
2172
|
+
popperInstanceRef.current = popperInstance;
|
|
2173
|
+
return () => {
|
|
2174
|
+
popperInstance.destroy();
|
|
2175
|
+
popperInstanceRef.current = null;
|
|
2176
|
+
};
|
|
2177
|
+
}, [referenceElement, popperElement, options.createPopper]);
|
|
2178
|
+
return {
|
|
2179
|
+
state: popperInstanceRef.current ? popperInstanceRef.current.state : null,
|
|
2180
|
+
styles: state.styles,
|
|
2181
|
+
attributes: state.attributes,
|
|
2182
|
+
update: popperInstanceRef.current ? popperInstanceRef.current.update : null,
|
|
2183
|
+
forceUpdate: popperInstanceRef.current ? popperInstanceRef.current.forceUpdate : null
|
|
2184
|
+
};
|
|
2185
|
+
};
|
|
2186
|
+
|
|
2187
|
+
const hash = {
|
|
2188
|
+
left: 'right',
|
|
2189
|
+
right: 'left',
|
|
2190
|
+
bottom: 'top',
|
|
2191
|
+
top: 'bottom',
|
|
2192
|
+
'top-start': 'bottom-end',
|
|
2193
|
+
'top-end': 'bottom-start',
|
|
2194
|
+
'bottom-start': 'top-end',
|
|
2195
|
+
'bottom-end': 'top-start',
|
|
2196
|
+
'left-start': 'right-end',
|
|
2197
|
+
'left-end': 'right-start',
|
|
2198
|
+
'right-start': 'left-end',
|
|
2199
|
+
'right-end': 'left-start'
|
|
2200
|
+
};
|
|
2201
|
+
const getOppositePlacement = (placement) => placement.replace(/left|right|bottom|top|top-start|top-end|bottom-start|bottom-end|right-start|right-end|left-start|left-end/g, (matched) => hash[matched]);
|
|
2202
|
+
const getOpacityTransition = (animationDuration) => `opacity ${animationDuration}ms cubic-bezier(.54, 1.5, .38, 1.11)`;
|
|
2203
|
+
const Popper = ({ trigger, popper, direction = 'down', position = 'start', placement, width, minWidth = 'trigger', maxWidth, appendTo = () => document.body, zIndex = 9999, isVisible = true, positionModifiers, distance = 0, onMouseEnter, onMouseLeave, onFocus, onBlur, onDocumentClick, onTriggerClick, onTriggerEnter, onPopperClick, onPopperMouseEnter, onPopperMouseLeave, onDocumentKeyDown, enableFlip = true, flipBehavior = 'flip', triggerRef, popperRef, animationDuration = 0, entryDelay = 0, exitDelay = 0, onHidden = () => { }, onHide = () => { }, onMount = () => { }, onShow = () => { }, onShown = () => { }, preventOverflow = false }) => {
|
|
2204
|
+
var _a;
|
|
2205
|
+
const [triggerElement, setTriggerElement] = React.useState(null);
|
|
2206
|
+
const [refElement, setRefElement] = React.useState(null);
|
|
2207
|
+
const [popperElement, setPopperElement] = React.useState(null);
|
|
2208
|
+
const [popperContent, setPopperContent] = React.useState(null);
|
|
2209
|
+
const [ready, setReady] = React.useState(false);
|
|
2210
|
+
const [opacity, setOpacity] = React.useState(0);
|
|
2211
|
+
const [internalIsVisible, setInternalIsVisible] = React.useState(isVisible);
|
|
2212
|
+
const transitionTimerRef = React.useRef(null);
|
|
2213
|
+
const showTimerRef = React.useRef(null);
|
|
2214
|
+
const hideTimerRef = React.useRef(null);
|
|
2215
|
+
const prevExitDelayRef = React.useRef();
|
|
2216
|
+
const refOrTrigger = refElement || triggerElement;
|
|
2217
|
+
const showPopper = isVisible || internalIsVisible;
|
|
2218
|
+
const triggerParent = (_a = ((triggerRef === null || triggerRef === void 0 ? void 0 : triggerRef.current) || triggerElement)) === null || _a === void 0 ? void 0 : _a.parentElement;
|
|
2219
|
+
const languageDirection = getLanguageDirection(triggerParent);
|
|
2220
|
+
const internalPosition = React.useMemo(() => {
|
|
2221
|
+
const fixedPositions = { left: 'left', right: 'right', center: 'center' };
|
|
2222
|
+
const positionMap = {
|
|
2223
|
+
ltr: Object.assign({ start: 'left', end: 'right' }, fixedPositions),
|
|
2224
|
+
rtl: Object.assign({ start: 'right', end: 'left' }, fixedPositions)
|
|
2225
|
+
};
|
|
2226
|
+
return positionMap[languageDirection][position];
|
|
2227
|
+
}, [position, languageDirection]);
|
|
2228
|
+
const onDocumentClickCallback = React.useCallback((event) => onDocumentClick(event, refOrTrigger, popperElement), [showPopper, triggerElement, refElement, popperElement, onDocumentClick]);
|
|
2229
|
+
React.useEffect(() => {
|
|
2230
|
+
setReady(true);
|
|
2231
|
+
onMount();
|
|
2232
|
+
}, []);
|
|
2233
|
+
// Cancel all timers on unmount
|
|
2234
|
+
React.useEffect(() => () => {
|
|
2235
|
+
clearTimeouts([transitionTimerRef, hideTimerRef, showTimerRef]);
|
|
2236
|
+
}, []);
|
|
2237
|
+
React.useEffect(() => {
|
|
2238
|
+
if (triggerRef) {
|
|
2239
|
+
if (triggerRef.current) {
|
|
2240
|
+
setRefElement(triggerRef.current);
|
|
2241
|
+
}
|
|
2242
|
+
else if (typeof triggerRef === 'function') {
|
|
2243
|
+
setRefElement(triggerRef());
|
|
2244
|
+
}
|
|
2245
|
+
}
|
|
2246
|
+
}, [triggerRef, trigger]);
|
|
2247
|
+
React.useEffect(() => {
|
|
2248
|
+
// When the popperRef is defined or the popper visibility changes, ensure the popper element is up to date
|
|
2249
|
+
if (popperRef) {
|
|
2250
|
+
if (popperRef.current) {
|
|
2251
|
+
setPopperElement(popperRef.current);
|
|
2252
|
+
}
|
|
2253
|
+
else if (typeof popperRef === 'function') {
|
|
2254
|
+
setPopperElement(popperRef());
|
|
2255
|
+
}
|
|
2256
|
+
}
|
|
2257
|
+
}, [showPopper, popperRef]);
|
|
2258
|
+
React.useEffect(() => {
|
|
2259
|
+
// Trigger a Popper update when content changes.
|
|
2260
|
+
const observer = new MutationObserver(() => {
|
|
2261
|
+
update && update();
|
|
2262
|
+
});
|
|
2263
|
+
popperElement && observer.observe(popperElement, { attributes: true, childList: true, subtree: true });
|
|
2264
|
+
return () => {
|
|
2265
|
+
observer.disconnect();
|
|
2266
|
+
};
|
|
2267
|
+
}, [popperElement]);
|
|
2268
|
+
const addEventListener = (listener, element, event, capture = false) => {
|
|
2269
|
+
if (listener && element) {
|
|
2270
|
+
element.addEventListener(event, listener, { capture });
|
|
2271
|
+
}
|
|
2272
|
+
};
|
|
2273
|
+
const removeEventListener = (listener, element, event, capture = false) => {
|
|
2274
|
+
if (listener && element) {
|
|
2275
|
+
element.removeEventListener(event, listener, { capture });
|
|
2276
|
+
}
|
|
2277
|
+
};
|
|
2278
|
+
React.useEffect(() => {
|
|
2279
|
+
addEventListener(onMouseEnter, refOrTrigger, 'mouseenter');
|
|
2280
|
+
addEventListener(onMouseLeave, refOrTrigger, 'mouseleave');
|
|
2281
|
+
addEventListener(onFocus, refOrTrigger, 'focus');
|
|
2282
|
+
addEventListener(onBlur, refOrTrigger, 'blur');
|
|
2283
|
+
addEventListener(onTriggerClick, refOrTrigger, 'click');
|
|
2284
|
+
addEventListener(onTriggerEnter, refOrTrigger, 'keydown');
|
|
2285
|
+
addEventListener(onPopperClick, popperElement, 'click');
|
|
2286
|
+
addEventListener(onPopperMouseEnter, popperElement, 'mouseenter');
|
|
2287
|
+
addEventListener(onPopperMouseLeave, popperElement, 'mouseleave');
|
|
2288
|
+
onDocumentClick && addEventListener(onDocumentClickCallback, document, 'click', true);
|
|
2289
|
+
addEventListener(onDocumentKeyDown, document, 'keydown', true);
|
|
2290
|
+
return () => {
|
|
2291
|
+
removeEventListener(onMouseEnter, refOrTrigger, 'mouseenter');
|
|
2292
|
+
removeEventListener(onMouseLeave, refOrTrigger, 'mouseleave');
|
|
2293
|
+
removeEventListener(onFocus, refOrTrigger, 'focus');
|
|
2294
|
+
removeEventListener(onBlur, refOrTrigger, 'blur');
|
|
2295
|
+
removeEventListener(onTriggerClick, refOrTrigger, 'click');
|
|
2296
|
+
removeEventListener(onTriggerEnter, refOrTrigger, 'keydown');
|
|
2297
|
+
removeEventListener(onPopperClick, popperElement, 'click');
|
|
2298
|
+
removeEventListener(onPopperMouseEnter, popperElement, 'mouseenter');
|
|
2299
|
+
removeEventListener(onPopperMouseLeave, popperElement, 'mouseleave');
|
|
2300
|
+
onDocumentClick && removeEventListener(onDocumentClickCallback, document, 'click', true);
|
|
2301
|
+
removeEventListener(onDocumentKeyDown, document, 'keydown', true);
|
|
2302
|
+
};
|
|
2303
|
+
}, [
|
|
2304
|
+
triggerElement,
|
|
2305
|
+
popperElement,
|
|
2306
|
+
onMouseEnter,
|
|
2307
|
+
onMouseLeave,
|
|
2308
|
+
onFocus,
|
|
2309
|
+
onBlur,
|
|
2310
|
+
onTriggerClick,
|
|
2311
|
+
onTriggerEnter,
|
|
2312
|
+
onPopperClick,
|
|
2313
|
+
onPopperMouseEnter,
|
|
2314
|
+
onPopperMouseLeave,
|
|
2315
|
+
onDocumentClick,
|
|
2316
|
+
onDocumentKeyDown,
|
|
2317
|
+
refElement
|
|
2318
|
+
]);
|
|
2319
|
+
const getPlacement = () => {
|
|
2320
|
+
if (placement) {
|
|
2321
|
+
return placement;
|
|
2322
|
+
}
|
|
2323
|
+
let convertedPlacement = direction === 'up' ? 'top' : 'bottom';
|
|
2324
|
+
if (internalPosition !== 'center') {
|
|
2325
|
+
convertedPlacement = `${convertedPlacement}-${internalPosition === 'right' ? 'end' : 'start'}`;
|
|
2326
|
+
}
|
|
2327
|
+
return convertedPlacement;
|
|
2328
|
+
};
|
|
2329
|
+
const getPlacementMemo = React.useMemo(getPlacement, [direction, internalPosition, placement]);
|
|
2330
|
+
const getOppositePlacementMemo = React.useMemo(() => getOppositePlacement(getPlacement()), [direction, internalPosition, placement]);
|
|
2331
|
+
const widthMods = React.useMemo(() => ({
|
|
2332
|
+
name: 'widthMods',
|
|
2333
|
+
enabled: width !== undefined || minWidth !== undefined || maxWidth !== undefined,
|
|
2334
|
+
phase: 'beforeWrite',
|
|
2335
|
+
requires: ['computeStyles'],
|
|
2336
|
+
fn: ({ state }) => {
|
|
2337
|
+
const triggerWidth = state.rects.reference.width;
|
|
2338
|
+
if (width) {
|
|
2339
|
+
state.styles.popper.width = width === 'trigger' ? `${triggerWidth}px` : width;
|
|
2340
|
+
}
|
|
2341
|
+
if (minWidth) {
|
|
2342
|
+
state.styles.popper.minWidth = minWidth === 'trigger' ? `${triggerWidth}px` : minWidth;
|
|
2343
|
+
}
|
|
2344
|
+
if (maxWidth) {
|
|
2345
|
+
state.styles.popper.maxWidth = maxWidth === 'trigger' ? `${triggerWidth}px` : maxWidth;
|
|
2346
|
+
}
|
|
2347
|
+
},
|
|
2348
|
+
effect: ({ state }) => {
|
|
2349
|
+
const triggerWidth = state.elements.reference.offsetWidth;
|
|
2350
|
+
if (width) {
|
|
2351
|
+
state.elements.popper.style.width = width === 'trigger' ? `${triggerWidth}px` : width;
|
|
2352
|
+
}
|
|
2353
|
+
if (minWidth) {
|
|
2354
|
+
state.elements.popper.style.minWidth = minWidth === 'trigger' ? `${triggerWidth}px` : minWidth;
|
|
2355
|
+
}
|
|
2356
|
+
if (maxWidth) {
|
|
2357
|
+
state.elements.popper.style.maxWidth = maxWidth === 'trigger' ? `${triggerWidth}px` : maxWidth;
|
|
2358
|
+
}
|
|
2359
|
+
return () => { };
|
|
2360
|
+
}
|
|
2361
|
+
}), [width, minWidth, maxWidth]);
|
|
2362
|
+
const { styles: popperStyles, attributes, update, forceUpdate } = usePopper(refOrTrigger, popperElement, {
|
|
2363
|
+
placement: getPlacementMemo,
|
|
2364
|
+
modifiers: [
|
|
2365
|
+
{
|
|
2366
|
+
name: 'offset',
|
|
2367
|
+
options: {
|
|
2368
|
+
offset: [0, distance]
|
|
2369
|
+
}
|
|
2370
|
+
},
|
|
2371
|
+
{
|
|
2372
|
+
name: 'preventOverflow',
|
|
2373
|
+
enabled: preventOverflow
|
|
2374
|
+
},
|
|
2375
|
+
{
|
|
2376
|
+
// adds attribute [data-popper-reference-hidden] to the popper element which can be used to hide it using CSS
|
|
2377
|
+
name: 'hide',
|
|
2378
|
+
enabled: true
|
|
2379
|
+
},
|
|
2380
|
+
{
|
|
2381
|
+
name: 'flip',
|
|
2382
|
+
enabled: getPlacementMemo.startsWith('auto') || enableFlip,
|
|
2383
|
+
options: {
|
|
2384
|
+
fallbackPlacements: flipBehavior === 'flip' ? [getOppositePlacementMemo] : flipBehavior
|
|
2385
|
+
}
|
|
2386
|
+
},
|
|
2387
|
+
widthMods
|
|
2388
|
+
]
|
|
2389
|
+
});
|
|
2390
|
+
/** We want to forceUpdate only when a tooltip's content is dynamically updated.
|
|
2391
|
+
* TODO: Investigate into 3rd party libraries for a less limited/specific solution
|
|
2392
|
+
*/
|
|
2393
|
+
React.useEffect(() => {
|
|
2394
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
2395
|
+
// currentPopperContent = {tooltip children} || {dropdown children}
|
|
2396
|
+
const currentPopperContent = ((_d = (_c = (_b = (_a = popper === null || popper === void 0 ? void 0 : popper.props) === null || _a === void 0 ? void 0 : _a.children) === null || _b === void 0 ? void 0 : _b[1]) === null || _c === void 0 ? void 0 : _c.props) === null || _d === void 0 ? void 0 : _d.children) || ((_g = (_f = (_e = popper === null || popper === void 0 ? void 0 : popper.props) === null || _e === void 0 ? void 0 : _e.children) === null || _f === void 0 ? void 0 : _f.props) === null || _g === void 0 ? void 0 : _g.children);
|
|
2397
|
+
setPopperContent(currentPopperContent);
|
|
2398
|
+
if (currentPopperContent && popperContent && currentPopperContent !== popperContent) {
|
|
2399
|
+
forceUpdate && forceUpdate();
|
|
2400
|
+
}
|
|
2401
|
+
}, [popper]);
|
|
2402
|
+
React.useEffect(() => {
|
|
2403
|
+
if (prevExitDelayRef.current < exitDelay) {
|
|
2404
|
+
clearTimeouts([transitionTimerRef, hideTimerRef]);
|
|
2405
|
+
hideTimerRef.current = setTimeout(() => {
|
|
2406
|
+
transitionTimerRef.current = setTimeout(() => {
|
|
2407
|
+
setInternalIsVisible(false);
|
|
2408
|
+
}, animationDuration);
|
|
2409
|
+
}, exitDelay);
|
|
2410
|
+
}
|
|
2411
|
+
prevExitDelayRef.current = exitDelay;
|
|
2412
|
+
}, [exitDelay]);
|
|
2413
|
+
const show = () => {
|
|
2414
|
+
onShow();
|
|
2415
|
+
clearTimeouts([transitionTimerRef, hideTimerRef]);
|
|
2416
|
+
showTimerRef.current = setTimeout(() => {
|
|
2417
|
+
setInternalIsVisible(true);
|
|
2418
|
+
setOpacity(1);
|
|
2419
|
+
onShown();
|
|
2420
|
+
}, entryDelay);
|
|
2421
|
+
};
|
|
2422
|
+
const hide = () => {
|
|
2423
|
+
onHide();
|
|
2424
|
+
clearTimeouts([showTimerRef]);
|
|
2425
|
+
hideTimerRef.current = setTimeout(() => {
|
|
2426
|
+
setOpacity(0);
|
|
2427
|
+
transitionTimerRef.current = setTimeout(() => {
|
|
2428
|
+
setInternalIsVisible(false);
|
|
2429
|
+
onHidden();
|
|
2430
|
+
}, animationDuration);
|
|
2431
|
+
}, exitDelay);
|
|
2432
|
+
};
|
|
2433
|
+
React.useEffect(() => {
|
|
2434
|
+
if (isVisible) {
|
|
2435
|
+
show();
|
|
2436
|
+
}
|
|
2437
|
+
else {
|
|
2438
|
+
hide();
|
|
2439
|
+
}
|
|
2440
|
+
}, [isVisible]);
|
|
2441
|
+
// Returns the CSS modifier class in order to place the Popper's arrow properly
|
|
2442
|
+
// Depends on the position of the Popper relative to the reference element
|
|
2443
|
+
const modifierFromPopperPosition = () => {
|
|
2444
|
+
if (attributes && attributes.popper && attributes.popper['data-popper-placement']) {
|
|
2445
|
+
const popperPlacement = attributes.popper['data-popper-placement'];
|
|
2446
|
+
return positionModifiers[popperPlacement];
|
|
2447
|
+
}
|
|
2448
|
+
return positionModifiers.top;
|
|
2449
|
+
};
|
|
2450
|
+
const options = Object.assign({ className: css(popper.props && popper.props.className, positionModifiers && modifierFromPopperPosition()), style: Object.assign(Object.assign(Object.assign({}, ((popper.props && popper.props.style) || {})), popperStyles.popper), { zIndex,
|
|
2451
|
+
opacity, transition: getOpacityTransition(animationDuration) }) }, attributes.popper);
|
|
2452
|
+
const getMenuWithPopper = () => {
|
|
2453
|
+
const localPopper = React.cloneElement(popper, options);
|
|
2454
|
+
return popperRef ? (localPopper) : (React.createElement("div", { style: { display: 'contents' }, ref: (node) => setPopperElement(node === null || node === void 0 ? void 0 : node.firstElementChild) }, localPopper));
|
|
2455
|
+
};
|
|
2456
|
+
const getPopper = () => {
|
|
2457
|
+
if (appendTo === 'inline') {
|
|
2458
|
+
return getMenuWithPopper();
|
|
2459
|
+
}
|
|
2460
|
+
else {
|
|
2461
|
+
const target = typeof appendTo === 'function' ? appendTo() : appendTo;
|
|
2462
|
+
return ReactDOM.createPortal(getMenuWithPopper(), target);
|
|
2463
|
+
}
|
|
2464
|
+
};
|
|
2465
|
+
return (React.createElement(React.Fragment, null,
|
|
2466
|
+
!triggerRef && trigger && React.isValidElement(trigger) && (React.createElement("div", { style: { display: 'contents' }, ref: (node) => setTriggerElement(node === null || node === void 0 ? void 0 : node.firstElementChild) }, trigger)),
|
|
2467
|
+
triggerRef && trigger && React.isValidElement(trigger) && trigger,
|
|
2468
|
+
ready && showPopper && getPopper()));
|
|
2469
|
+
};
|
|
2470
|
+
Popper.displayName = 'Popper';
|
|
2471
|
+
|
|
2472
|
+
/**
|
|
2473
|
+
* This function is a helper for handling basic arrow keyboard interactions. If a component already has its own key handler and event start up/tear down, this function may be easier to integrate in over the full component.
|
|
2474
|
+
*
|
|
2475
|
+
* @param {event} event Event triggered by the keyboard
|
|
2476
|
+
* @param {element[]} navigableElements Valid traversable elements of the container
|
|
2477
|
+
* @param {function} isActiveElement Callback to determine if a given element from the navigable elements array is the active element of the page
|
|
2478
|
+
* @param {function} getFocusableElement Callback returning the focusable element of a given element from the navigable elements array
|
|
2479
|
+
* @param {string[]} validSiblingTags Valid sibling tags that horizontal arrow handling will focus
|
|
2480
|
+
* @param {boolean} noVerticalArrowHandling Flag indicating that the included vertical arrow key handling should be ignored
|
|
2481
|
+
* @param {boolean} noHorizontalArrowHandling Flag indicating that the included horizontal arrow key handling should be ignored
|
|
2482
|
+
* @param {boolean} updateTabIndex Flag indicating that the tabIndex of the currently focused element and next focused element should be updated, in the case of using a roving tabIndex
|
|
2483
|
+
* @param {boolean} onlyTraverseSiblings Flag indicating that next focusable element of a horizontal movement will be this element's sibling
|
|
2484
|
+
*/
|
|
2485
|
+
const handleArrows = (event, navigableElements, isActiveElement = (element) => document.activeElement.contains(element), getFocusableElement = (element) => element, validSiblingTags = ['A', 'BUTTON', 'INPUT'], noVerticalArrowHandling = false, noHorizontalArrowHandling = false, updateTabIndex = true, onlyTraverseSiblings = true) => {
|
|
2486
|
+
const activeElement = document.activeElement;
|
|
2487
|
+
const key = event.key;
|
|
2488
|
+
let moveTarget = null;
|
|
2489
|
+
// Handle vertical arrow keys. If noVerticalArrowHandling is passed, skip this block
|
|
2490
|
+
if (!noVerticalArrowHandling) {
|
|
2491
|
+
if (['ArrowUp', 'ArrowDown'].includes(key)) {
|
|
2492
|
+
event.preventDefault();
|
|
2493
|
+
event.stopImmediatePropagation(); // For menus in menus
|
|
2494
|
+
// Traverse navigableElements to find the element which is currently active
|
|
2495
|
+
let currentIndex = -1;
|
|
2496
|
+
// while (currentIndex === -1) {
|
|
2497
|
+
navigableElements.forEach((element, index) => {
|
|
2498
|
+
if (isActiveElement(element)) {
|
|
2499
|
+
// Once found, move up or down the array by 1. Determined by the vertical arrow key direction
|
|
2500
|
+
let increment = 0;
|
|
2501
|
+
// keep increasing the increment until you've tried the whole navigableElement
|
|
2502
|
+
while (!moveTarget && increment < navigableElements.length && increment * -1 < navigableElements.length) {
|
|
2503
|
+
key === 'ArrowUp' ? increment-- : increment++;
|
|
2504
|
+
currentIndex = index + increment;
|
|
2505
|
+
if (currentIndex >= navigableElements.length) {
|
|
2506
|
+
currentIndex = 0;
|
|
2507
|
+
}
|
|
2508
|
+
if (currentIndex < 0) {
|
|
2509
|
+
currentIndex = navigableElements.length - 1;
|
|
2510
|
+
}
|
|
2511
|
+
// Set the next target element (undefined if none found)
|
|
2512
|
+
moveTarget = getFocusableElement(navigableElements[currentIndex]);
|
|
2513
|
+
}
|
|
2514
|
+
}
|
|
2515
|
+
});
|
|
2516
|
+
// }
|
|
2517
|
+
}
|
|
2518
|
+
}
|
|
2519
|
+
// Handle horizontal arrow keys. If noHorizontalArrowHandling is passed, skip this block
|
|
2520
|
+
if (!noHorizontalArrowHandling) {
|
|
2521
|
+
if (['ArrowLeft', 'ArrowRight'].includes(key)) {
|
|
2522
|
+
event.preventDefault();
|
|
2523
|
+
event.stopImmediatePropagation(); // For menus in menus
|
|
2524
|
+
let currentIndex = -1;
|
|
2525
|
+
navigableElements.forEach((element, index) => {
|
|
2526
|
+
if (isActiveElement(element)) {
|
|
2527
|
+
const activeRow = navigableElements[index].querySelectorAll(validSiblingTags.join(',')); // all focusable elements in my row
|
|
2528
|
+
if (!activeRow.length || onlyTraverseSiblings) {
|
|
2529
|
+
let nextSibling = activeElement;
|
|
2530
|
+
while (nextSibling) {
|
|
2531
|
+
const isDirectChildOfNavigableElement = nextSibling.parentElement === element;
|
|
2532
|
+
const nextSiblingMainElement = isDirectChildOfNavigableElement ? nextSibling : nextSibling.parentElement;
|
|
2533
|
+
nextSibling =
|
|
2534
|
+
key === 'ArrowLeft'
|
|
2535
|
+
? nextSiblingMainElement.previousElementSibling
|
|
2536
|
+
: nextSiblingMainElement.nextElementSibling;
|
|
2537
|
+
if (nextSibling) {
|
|
2538
|
+
if (validSiblingTags.includes(nextSibling.tagName)) {
|
|
2539
|
+
moveTarget = nextSibling;
|
|
2540
|
+
break;
|
|
2541
|
+
}
|
|
2542
|
+
// For cases where the validSiblingTag is inside a div wrapper
|
|
2543
|
+
if (validSiblingTags.includes(nextSibling.children[0].tagName)) {
|
|
2544
|
+
moveTarget = nextSibling.children[0];
|
|
2545
|
+
break;
|
|
2546
|
+
}
|
|
2547
|
+
}
|
|
2548
|
+
}
|
|
2549
|
+
}
|
|
2550
|
+
else {
|
|
2551
|
+
activeRow.forEach((focusableElement, index) => {
|
|
2552
|
+
if (event.target === focusableElement) {
|
|
2553
|
+
const increment = key === 'ArrowLeft' ? -1 : 1;
|
|
2554
|
+
currentIndex = index + increment;
|
|
2555
|
+
if (currentIndex >= activeRow.length) {
|
|
2556
|
+
currentIndex = 0;
|
|
2557
|
+
}
|
|
2558
|
+
if (currentIndex < 0) {
|
|
2559
|
+
currentIndex = activeRow.length - 1;
|
|
2560
|
+
}
|
|
2561
|
+
moveTarget = activeRow[currentIndex];
|
|
2562
|
+
}
|
|
2563
|
+
});
|
|
2564
|
+
}
|
|
2565
|
+
}
|
|
2566
|
+
});
|
|
2567
|
+
}
|
|
2568
|
+
}
|
|
2569
|
+
if (moveTarget) {
|
|
2570
|
+
// If updateTabIndex is true, set the previously focussed element's tabIndex to -1 and the next focussed element's tabIndex to 0
|
|
2571
|
+
// This updates the tabIndex for a roving tabIndex
|
|
2572
|
+
if (updateTabIndex) {
|
|
2573
|
+
activeElement.tabIndex = -1;
|
|
2574
|
+
moveTarget.tabIndex = 0;
|
|
2575
|
+
}
|
|
2576
|
+
// If a move target has been set by either arrow handler, focus that target
|
|
2577
|
+
moveTarget.focus();
|
|
2578
|
+
}
|
|
2579
|
+
};
|
|
2580
|
+
/**
|
|
2581
|
+
* This function is a helper for setting the initial tabIndexes in a roving tabIndex
|
|
2582
|
+
*
|
|
2583
|
+
* @param {HTMLElement[]} options Array of elements which should have a tabIndex of -1, except for the first element which will have a tabIndex of 0
|
|
2584
|
+
*/
|
|
2585
|
+
const setTabIndex = (options) => {
|
|
2586
|
+
if (options && options.length > 0) {
|
|
2587
|
+
// Iterate the options and set the tabIndex to -1 on every option
|
|
2588
|
+
options.forEach((option) => {
|
|
2589
|
+
option.tabIndex = -1;
|
|
2590
|
+
});
|
|
2591
|
+
// Manually set the tabIndex of the first option to 0
|
|
2592
|
+
options[0].tabIndex = 0;
|
|
2593
|
+
}
|
|
2594
|
+
};
|
|
2595
|
+
/**
|
|
2596
|
+
* This function is used in Dropdown, Select and MenuContainer as a default toggle keydown behavior. When the toggle has focus and the menu is open, pressing the up/down arrow keys will focus a valid non-disabled menu item - the first item for the down arrow key and last item for the up arrow key.
|
|
2597
|
+
*
|
|
2598
|
+
* @param event Event triggered by the keyboard
|
|
2599
|
+
* @param menuRef Menu reference
|
|
2600
|
+
*/
|
|
2601
|
+
const onToggleArrowKeydownDefault = (event, menuRef) => {
|
|
2602
|
+
var _a;
|
|
2603
|
+
if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp') {
|
|
2604
|
+
return;
|
|
2605
|
+
}
|
|
2606
|
+
event.preventDefault();
|
|
2607
|
+
const listItems = Array.from((_a = menuRef.current) === null || _a === void 0 ? void 0 : _a.querySelectorAll('li'));
|
|
2608
|
+
const focusableElements = listItems
|
|
2609
|
+
.map((li) => li.querySelector('button:not(:disabled),input:not(:disabled),a:not([aria-disabled="true"])'))
|
|
2610
|
+
.filter((el) => el !== null);
|
|
2611
|
+
let focusableElement;
|
|
2612
|
+
if (event.key === 'ArrowDown') {
|
|
2613
|
+
focusableElement = focusableElements[0];
|
|
2614
|
+
}
|
|
2615
|
+
else {
|
|
2616
|
+
focusableElement = focusableElements[focusableElements.length - 1];
|
|
2617
|
+
}
|
|
2618
|
+
focusableElement && focusableElement.focus();
|
|
2619
|
+
};
|
|
2620
|
+
class KeyboardHandler extends React.Component {
|
|
2621
|
+
constructor() {
|
|
2622
|
+
super(...arguments);
|
|
2623
|
+
this.keyHandler = (event) => {
|
|
2624
|
+
const { isEventFromContainer } = this.props;
|
|
2625
|
+
// If the passed keyboard event is not from the container, ignore the event by returning
|
|
2626
|
+
if (isEventFromContainer ? !isEventFromContainer(event) : !this._isEventFromContainer(event)) {
|
|
2627
|
+
return;
|
|
2628
|
+
}
|
|
2629
|
+
const { isActiveElement, getFocusableElement, noVerticalArrowHandling, noHorizontalArrowHandling, noEnterHandling, noSpaceHandling, updateTabIndex, validSiblingTags, additionalKeyHandler, createNavigableElements, onlyTraverseSiblings } = this.props;
|
|
2630
|
+
// Pass the event off to be handled by any custom handler
|
|
2631
|
+
additionalKeyHandler && additionalKeyHandler(event);
|
|
2632
|
+
// Initalize navigableElements from the createNavigableElements callback
|
|
2633
|
+
const navigableElements = createNavigableElements();
|
|
2634
|
+
if (!navigableElements) {
|
|
2635
|
+
// eslint-disable-next-line no-console
|
|
2636
|
+
console.warn('No navigable elements have been passed to the KeyboardHandler. Keyboard navigation provided by this component will be ignored.');
|
|
2637
|
+
return;
|
|
2638
|
+
}
|
|
2639
|
+
const key = event.key;
|
|
2640
|
+
// Handle enter key. If noEnterHandling is passed, skip this block
|
|
2641
|
+
if (!noEnterHandling) {
|
|
2642
|
+
if (key === 'Enter') {
|
|
2643
|
+
event.preventDefault();
|
|
2644
|
+
event.stopImmediatePropagation(); // For menus in menus
|
|
2645
|
+
document.activeElement.click();
|
|
2646
|
+
}
|
|
2647
|
+
}
|
|
2648
|
+
// Handle space key. If noSpaceHandling is passed, skip this block
|
|
2649
|
+
if (!noSpaceHandling) {
|
|
2650
|
+
if (key === ' ') {
|
|
2651
|
+
event.preventDefault();
|
|
2652
|
+
event.stopImmediatePropagation(); // For menus in menus
|
|
2653
|
+
document.activeElement.click();
|
|
2654
|
+
}
|
|
2655
|
+
}
|
|
2656
|
+
// Inject helper handler for arrow navigation
|
|
2657
|
+
handleArrows(event, navigableElements, isActiveElement, getFocusableElement, validSiblingTags, noVerticalArrowHandling, noHorizontalArrowHandling, updateTabIndex, onlyTraverseSiblings);
|
|
2658
|
+
};
|
|
2659
|
+
this._isEventFromContainer = (event) => {
|
|
2660
|
+
const { containerRef } = this.props;
|
|
2661
|
+
return containerRef.current && containerRef.current.contains(event.target);
|
|
2662
|
+
};
|
|
2663
|
+
}
|
|
2664
|
+
componentDidMount() {
|
|
2665
|
+
if (canUseDOM) {
|
|
2666
|
+
window.addEventListener('keydown', this.keyHandler);
|
|
2667
|
+
}
|
|
2668
|
+
}
|
|
2669
|
+
componentWillUnmount() {
|
|
2670
|
+
if (canUseDOM) {
|
|
2671
|
+
window.removeEventListener('keydown', this.keyHandler);
|
|
2672
|
+
}
|
|
2673
|
+
}
|
|
2674
|
+
render() {
|
|
2675
|
+
return null;
|
|
2676
|
+
}
|
|
2677
|
+
}
|
|
2678
|
+
KeyboardHandler.displayName = 'KeyboardHandler';
|
|
2679
|
+
KeyboardHandler.defaultProps = {
|
|
2680
|
+
containerRef: null,
|
|
2681
|
+
createNavigableElements: () => null,
|
|
2682
|
+
isActiveElement: (navigableElement) => document.activeElement === navigableElement,
|
|
2683
|
+
getFocusableElement: (navigableElement) => navigableElement,
|
|
2684
|
+
validSiblingTags: ['BUTTON', 'A'],
|
|
2685
|
+
onlyTraverseSiblings: true,
|
|
2686
|
+
updateTabIndex: true,
|
|
2687
|
+
noHorizontalArrowHandling: false,
|
|
2688
|
+
noVerticalArrowHandling: false,
|
|
2689
|
+
noEnterHandling: false,
|
|
2690
|
+
noSpaceHandling: false
|
|
2691
|
+
};
|
|
2692
|
+
|
|
2693
|
+
const styles$4 = {
|
|
2694
|
+
"button": "pf-v6-c-button",
|
|
2695
|
+
"buttonCount": "pf-v6-c-button__count",
|
|
2696
|
+
"buttonIcon": "pf-v6-c-button__icon",
|
|
2697
|
+
"buttonProgress": "pf-v6-c-button__progress",
|
|
2698
|
+
"modifiers": {
|
|
2699
|
+
"primary": "pf-m-primary",
|
|
2700
|
+
"unread": "pf-m-unread",
|
|
2701
|
+
"secondary": "pf-m-secondary",
|
|
2702
|
+
"danger": "pf-m-danger",
|
|
2703
|
+
"tertiary": "pf-m-tertiary",
|
|
2704
|
+
"link": "pf-m-link",
|
|
2705
|
+
"inline": "pf-m-inline",
|
|
2706
|
+
"displayLg": "pf-m-display-lg",
|
|
2707
|
+
"warning": "pf-m-warning",
|
|
2708
|
+
"control": "pf-m-control",
|
|
2709
|
+
"stateful": "pf-m-stateful",
|
|
2710
|
+
"read": "pf-m-read",
|
|
2711
|
+
"attention": "pf-m-attention",
|
|
2712
|
+
"plain": "pf-m-plain",
|
|
2713
|
+
"noPadding": "pf-m-no-padding",
|
|
2714
|
+
"block": "pf-m-block",
|
|
2715
|
+
"small": "pf-m-small",
|
|
2716
|
+
"clicked": "pf-m-clicked",
|
|
2717
|
+
"disabled": "pf-m-disabled",
|
|
2718
|
+
"ariaDisabled": "pf-m-aria-disabled",
|
|
2719
|
+
"progress": "pf-m-progress",
|
|
2720
|
+
"inProgress": "pf-m-in-progress",
|
|
2721
|
+
"start": "pf-m-start",
|
|
2722
|
+
"end": "pf-m-end"
|
|
2723
|
+
}};
|
|
2724
|
+
|
|
2725
|
+
const styles$3 = {
|
|
2726
|
+
"modifiers": {
|
|
2727
|
+
"inline": "pf-m-inline",
|
|
2728
|
+
"sm": "pf-m-sm",
|
|
2729
|
+
"md": "pf-m-md",
|
|
2730
|
+
"lg": "pf-m-lg",
|
|
2731
|
+
"xl": "pf-m-xl"
|
|
2732
|
+
},
|
|
2733
|
+
"spinner": "pf-v6-c-spinner",
|
|
2734
|
+
"spinnerPath": "pf-v6-c-spinner__path"
|
|
2735
|
+
};
|
|
2736
|
+
|
|
2737
|
+
const c_spinner_diameter = {
|
|
2738
|
+
"name": "--pf-v6-c-spinner--diameter"};
|
|
2739
|
+
|
|
2740
|
+
var spinnerSize;
|
|
2741
|
+
(function (spinnerSize) {
|
|
2742
|
+
spinnerSize["sm"] = "sm";
|
|
2743
|
+
spinnerSize["md"] = "md";
|
|
2744
|
+
spinnerSize["lg"] = "lg";
|
|
2745
|
+
spinnerSize["xl"] = "xl";
|
|
2746
|
+
})(spinnerSize || (spinnerSize = {}));
|
|
2747
|
+
const Spinner = (_a) => {
|
|
2748
|
+
var { className = '', size = 'xl', 'aria-valuetext': ariaValueText = 'Loading...', diameter, isInline = false, 'aria-label': ariaLabel, 'aria-labelledBy': ariaLabelledBy } = _a, props = __rest(_a, ["className", "size", 'aria-valuetext', "diameter", "isInline", 'aria-label', 'aria-labelledBy']);
|
|
2749
|
+
return (React.createElement("svg", Object.assign({ className: css(styles$3.spinner, isInline ? styles$3.modifiers.inline : styles$3.modifiers[size], className), role: "progressbar", "aria-valuetext": ariaValueText, viewBox: "0 0 100 100" }, (diameter && { style: { [c_spinner_diameter.name]: diameter } }), (ariaLabel && { 'aria-label': ariaLabel }), (ariaLabelledBy && { 'aria-labelledBy': ariaLabelledBy }), (!ariaLabel && !ariaLabelledBy && { 'aria-label': 'Contents' }), props),
|
|
2750
|
+
React.createElement("circle", { className: styles$3.spinnerPath, cx: "50", cy: "50", r: "45", fill: "none" })));
|
|
2751
|
+
};
|
|
2752
|
+
Spinner.displayName = 'Spinner';
|
|
2753
|
+
|
|
2754
|
+
const styles$2 = {
|
|
2755
|
+
"badge": "pf-v6-c-badge",
|
|
2756
|
+
"modifiers": {
|
|
2757
|
+
"read": "pf-m-read",
|
|
2758
|
+
"unread": "pf-m-unread",
|
|
2759
|
+
"disabled": "pf-m-disabled"
|
|
2760
|
+
}
|
|
2761
|
+
};
|
|
2762
|
+
|
|
2763
|
+
const Badge = (_a) => {
|
|
2764
|
+
var { isRead = false, isDisabled = false, className = '', children = '', screenReaderText } = _a, props = __rest(_a, ["isRead", "isDisabled", "className", "children", "screenReaderText"]);
|
|
2765
|
+
return (React.createElement("span", Object.assign({}, props, { className: css(styles$2.badge, (isRead ? styles$2.modifiers.read : styles$2.modifiers.unread), isDisabled && styles$2.modifiers.disabled, className) }),
|
|
2766
|
+
children,
|
|
2767
|
+
screenReaderText && React.createElement("span", { className: "pf-v6-screen-reader" }, screenReaderText)));
|
|
2768
|
+
};
|
|
2769
|
+
Badge.displayName = 'Badge';
|
|
2770
|
+
|
|
2771
|
+
var ButtonVariant;
|
|
2772
|
+
(function (ButtonVariant) {
|
|
2773
|
+
ButtonVariant["primary"] = "primary";
|
|
2774
|
+
ButtonVariant["secondary"] = "secondary";
|
|
2775
|
+
ButtonVariant["tertiary"] = "tertiary";
|
|
2776
|
+
ButtonVariant["danger"] = "danger";
|
|
2777
|
+
ButtonVariant["warning"] = "warning";
|
|
2778
|
+
ButtonVariant["link"] = "link";
|
|
2779
|
+
ButtonVariant["plain"] = "plain";
|
|
2780
|
+
ButtonVariant["control"] = "control";
|
|
2781
|
+
ButtonVariant["stateful"] = "stateful";
|
|
2782
|
+
})(ButtonVariant || (ButtonVariant = {}));
|
|
2783
|
+
var ButtonType;
|
|
2784
|
+
(function (ButtonType) {
|
|
2785
|
+
ButtonType["button"] = "button";
|
|
2786
|
+
ButtonType["submit"] = "submit";
|
|
2787
|
+
ButtonType["reset"] = "reset";
|
|
2788
|
+
})(ButtonType || (ButtonType = {}));
|
|
2789
|
+
var ButtonSize;
|
|
2790
|
+
(function (ButtonSize) {
|
|
2791
|
+
ButtonSize["default"] = "default";
|
|
2792
|
+
ButtonSize["sm"] = "sm";
|
|
2793
|
+
ButtonSize["lg"] = "lg";
|
|
2794
|
+
})(ButtonSize || (ButtonSize = {}));
|
|
2795
|
+
var ButtonState;
|
|
2796
|
+
(function (ButtonState) {
|
|
2797
|
+
ButtonState["read"] = "read";
|
|
2798
|
+
ButtonState["unread"] = "unread";
|
|
2799
|
+
ButtonState["attention"] = "attention";
|
|
2800
|
+
})(ButtonState || (ButtonState = {}));
|
|
2801
|
+
const ButtonBase = (_a) => {
|
|
2802
|
+
var { children = null, className = '', component = 'button', isClicked = false, isBlock = false, isDisabled = false, isAriaDisabled = false, isLoading = null, isDanger = false, spinnerAriaValueText, spinnerAriaLabelledBy, spinnerAriaLabel, size = ButtonSize.default, inoperableEvents = ['onClick', 'onKeyPress'], isInline = false, type = ButtonType.button, variant = ButtonVariant.primary, state = ButtonState.unread, hasNoPadding = false, iconPosition = 'start', 'aria-label': ariaLabel = null, icon = null, role, ouiaId, ouiaSafe = true, tabIndex = null, innerRef, countOptions } = _a, props = __rest(_a, ["children", "className", "component", "isClicked", "isBlock", "isDisabled", "isAriaDisabled", "isLoading", "isDanger", "spinnerAriaValueText", "spinnerAriaLabelledBy", "spinnerAriaLabel", "size", "inoperableEvents", "isInline", "type", "variant", "state", "hasNoPadding", "iconPosition", 'aria-label', "icon", "role", "ouiaId", "ouiaSafe", "tabIndex", "innerRef", "countOptions"]);
|
|
2803
|
+
const ouiaProps = useOUIAProps(Button.displayName, ouiaId, ouiaSafe, variant);
|
|
2804
|
+
const Component = component;
|
|
2805
|
+
const isButtonElement = Component === 'button';
|
|
2806
|
+
const isInlineSpan = isInline && Component === 'span';
|
|
2807
|
+
const isIconAlignedAtEnd = iconPosition === 'end' || iconPosition === 'right';
|
|
2808
|
+
const preventedEvents = inoperableEvents.reduce((handlers, eventToPrevent) => (Object.assign(Object.assign({}, handlers), { [eventToPrevent]: (event) => {
|
|
2809
|
+
event.preventDefault();
|
|
2810
|
+
} })), {});
|
|
2811
|
+
const getDefaultTabIdx = () => {
|
|
2812
|
+
if (isDisabled) {
|
|
2813
|
+
return isButtonElement ? null : -1;
|
|
2814
|
+
}
|
|
2815
|
+
else if (isAriaDisabled) {
|
|
2816
|
+
return null;
|
|
2817
|
+
}
|
|
2818
|
+
else if (isInlineSpan) {
|
|
2819
|
+
return 0;
|
|
2820
|
+
}
|
|
2821
|
+
};
|
|
2822
|
+
const _icon = icon && (React.createElement("span", { className: css(styles$4.buttonIcon, children && styles$4.modifiers[isIconAlignedAtEnd ? 'end' : 'start']) }, icon));
|
|
2823
|
+
const _children = children && React.createElement("span", { className: css('pf-v6-c-button__text') }, children);
|
|
2824
|
+
return (React.createElement(Component, Object.assign({}, props, (isAriaDisabled ? preventedEvents : null), { "aria-disabled": isAriaDisabled || (!isButtonElement && isDisabled), "aria-label": ariaLabel, className: css(styles$4.button, styles$4.modifiers[variant], isBlock && styles$4.modifiers.block, isDisabled && !isButtonElement && styles$4.modifiers.disabled, isAriaDisabled && styles$4.modifiers.ariaDisabled, isClicked && styles$4.modifiers.clicked, isInline && variant === ButtonVariant.link && styles$4.modifiers.inline, isDanger && (variant === ButtonVariant.secondary || variant === ButtonVariant.link) && styles$4.modifiers.danger, isLoading !== null && variant !== ButtonVariant.plain && styles$4.modifiers.progress, isLoading && styles$4.modifiers.inProgress, hasNoPadding && variant === ButtonVariant.plain && styles$4.modifiers.noPadding, variant === ButtonVariant.stateful && styles$4.modifiers[state], size === ButtonSize.sm && styles$4.modifiers.small, size === ButtonSize.lg && styles$4.modifiers.displayLg, className), disabled: isButtonElement ? isDisabled : null, tabIndex: tabIndex !== null ? tabIndex : getDefaultTabIdx(), type: isButtonElement || isInlineSpan ? type : null, role: isInlineSpan ? 'button' : role, ref: innerRef }, ouiaProps),
|
|
2825
|
+
isLoading && (React.createElement("span", { className: css(styles$4.buttonProgress) },
|
|
2826
|
+
React.createElement(Spinner, { size: spinnerSize.md, isInline: isInline, "aria-valuetext": spinnerAriaValueText, "aria-label": spinnerAriaLabel, "aria-labelledby": spinnerAriaLabelledBy }))),
|
|
2827
|
+
isIconAlignedAtEnd ? (React.createElement(React.Fragment, null,
|
|
2828
|
+
_children,
|
|
2829
|
+
_icon)) : (React.createElement(React.Fragment, null,
|
|
2830
|
+
_icon,
|
|
2831
|
+
_children)),
|
|
2832
|
+
countOptions && (React.createElement("span", { className: css(styles$4.buttonCount, countOptions.className) },
|
|
2833
|
+
React.createElement(Badge, { isRead: countOptions.isRead, isDisabled: isDisabled }, countOptions.count)))));
|
|
2834
|
+
};
|
|
2835
|
+
const Button = React.forwardRef((props, ref) => (React.createElement(ButtonBase, Object.assign({ innerRef: ref }, props))));
|
|
2836
|
+
Button.displayName = 'Button';
|
|
2837
|
+
|
|
2838
|
+
const TimesIconConfig = {
|
|
2839
|
+
name: 'TimesIcon',
|
|
2840
|
+
height: 512,
|
|
2841
|
+
width: 352,
|
|
2842
|
+
svgPath: 'M242.72 256l100.07-100.07c12.28-12.28 12.28-32.19 0-44.48l-22.24-22.24c-12.28-12.28-32.19-12.28-44.48 0L176 189.28 75.93 89.21c-12.28-12.28-32.19-12.28-44.48 0L9.21 111.45c-12.28 12.28-12.28 32.19 0 44.48L109.28 256 9.21 356.07c-12.28 12.28-12.28 32.19 0 44.48l22.24 22.24c12.28 12.28 32.2 12.28 44.48 0L176 322.72l100.07 100.07c12.28 12.28 32.2 12.28 44.48 0l22.24-22.24c12.28-12.28 12.28-32.19 0-44.48L242.72 256z',
|
|
2843
|
+
yOffset: 0,
|
|
2844
|
+
xOffset: 0,
|
|
2845
|
+
};
|
|
2846
|
+
|
|
2847
|
+
const TimesIcon = createIcon(TimesIconConfig);
|
|
2848
|
+
|
|
2849
|
+
const styles$1 = {
|
|
2850
|
+
"modifiers": {
|
|
2851
|
+
"top": "pf-m-top",
|
|
2852
|
+
"topLeft": "pf-m-top-left",
|
|
2853
|
+
"topRight": "pf-m-top-right",
|
|
2854
|
+
"bottom": "pf-m-bottom",
|
|
2855
|
+
"bottomLeft": "pf-m-bottom-left",
|
|
2856
|
+
"bottomRight": "pf-m-bottom-right",
|
|
2857
|
+
"left": "pf-m-left",
|
|
2858
|
+
"leftTop": "pf-m-left-top",
|
|
2859
|
+
"leftBottom": "pf-m-left-bottom",
|
|
2860
|
+
"right": "pf-m-right",
|
|
2861
|
+
"rightTop": "pf-m-right-top",
|
|
2862
|
+
"rightBottom": "pf-m-right-bottom",
|
|
2863
|
+
"textAlignLeft": "pf-m-text-align-left"
|
|
2864
|
+
},
|
|
2865
|
+
"tooltip": "pf-v6-c-tooltip",
|
|
2866
|
+
"tooltipArrow": "pf-v6-c-tooltip__arrow",
|
|
2867
|
+
"tooltipContent": "pf-v6-c-tooltip__content"
|
|
2868
|
+
};
|
|
2869
|
+
|
|
2870
|
+
const TooltipContent = (_a) => {
|
|
2871
|
+
var { className, children, isLeftAligned } = _a, props = __rest(_a, ["className", "children", "isLeftAligned"]);
|
|
2872
|
+
return (React.createElement("div", Object.assign({ className: css(styles$1.tooltipContent, isLeftAligned && styles$1.modifiers.textAlignLeft, className) }, props), children));
|
|
2873
|
+
};
|
|
2874
|
+
TooltipContent.displayName = 'TooltipContent';
|
|
2875
|
+
|
|
2876
|
+
const TooltipArrow = (_a) => {
|
|
2877
|
+
var { className } = _a, props = __rest(_a, ["className"]);
|
|
2878
|
+
return React.createElement("div", Object.assign({ className: css(styles$1.tooltipArrow, className) }, props));
|
|
2879
|
+
};
|
|
2880
|
+
TooltipArrow.displayName = 'TooltipArrow';
|
|
2881
|
+
|
|
2882
|
+
const c_tooltip_MaxWidth = {
|
|
2883
|
+
"value": "18.75rem"};
|
|
2884
|
+
|
|
2885
|
+
var TooltipPosition;
|
|
2886
|
+
(function (TooltipPosition) {
|
|
2887
|
+
TooltipPosition["auto"] = "auto";
|
|
2888
|
+
TooltipPosition["top"] = "top";
|
|
2889
|
+
TooltipPosition["bottom"] = "bottom";
|
|
2890
|
+
TooltipPosition["left"] = "left";
|
|
2891
|
+
TooltipPosition["right"] = "right";
|
|
2892
|
+
TooltipPosition["topStart"] = "top-start";
|
|
2893
|
+
TooltipPosition["topEnd"] = "top-end";
|
|
2894
|
+
TooltipPosition["bottomStart"] = "bottom-start";
|
|
2895
|
+
TooltipPosition["bottomEnd"] = "bottom-end";
|
|
2896
|
+
TooltipPosition["leftStart"] = "left-start";
|
|
2897
|
+
TooltipPosition["leftEnd"] = "left-end";
|
|
2898
|
+
TooltipPosition["rightStart"] = "right-start";
|
|
2899
|
+
TooltipPosition["rightEnd"] = "right-end";
|
|
2900
|
+
})(TooltipPosition || (TooltipPosition = {}));
|
|
2901
|
+
// id for associating trigger with the content aria-describedby or aria-labelledby
|
|
2902
|
+
let pfTooltipIdCounter = 1;
|
|
2903
|
+
const Tooltip = (_a) => {
|
|
2904
|
+
var { content: bodyContent, position = 'top', trigger = 'mouseenter focus', isVisible = false, isContentLeftAligned = false, enableFlip = true, className = '', entryDelay = 300, exitDelay = 300, appendTo = () => document.body, zIndex = 9999, minWidth, maxWidth = c_tooltip_MaxWidth.value, distance = 15, aria = 'describedby',
|
|
2905
|
+
// For every initial starting position, there are 3 escape positions
|
|
2906
|
+
flipBehavior = ['top', 'right', 'bottom', 'left', 'top', 'right', 'bottom'], id = `pf-tooltip-${pfTooltipIdCounter++}`, children, animationDuration = 300, triggerRef, 'aria-live': ariaLive = triggerRef ? 'polite' : 'off', onTooltipHidden = () => { } } = _a, rest = __rest(_a, ["content", "position", "trigger", "isVisible", "isContentLeftAligned", "enableFlip", "className", "entryDelay", "exitDelay", "appendTo", "zIndex", "minWidth", "maxWidth", "distance", "aria", "flipBehavior", "id", "children", "animationDuration", "triggerRef", 'aria-live', "onTooltipHidden"]);
|
|
2907
|
+
const triggerOnMouseenter = trigger.includes('mouseenter');
|
|
2908
|
+
const triggerOnFocus = trigger.includes('focus');
|
|
2909
|
+
const triggerOnClick = trigger.includes('click');
|
|
2910
|
+
const triggerManually = trigger === 'manual';
|
|
2911
|
+
const [visible, setVisible] = React.useState(false);
|
|
2912
|
+
const popperRef = React.createRef();
|
|
2913
|
+
const onDocumentKeyDown = (event) => {
|
|
2914
|
+
if (!triggerManually) {
|
|
2915
|
+
if (event.key === KeyTypes.Escape && visible) {
|
|
2916
|
+
hide();
|
|
2917
|
+
}
|
|
2918
|
+
}
|
|
2919
|
+
};
|
|
2920
|
+
const onTriggerEnter = (event) => {
|
|
2921
|
+
if (event.key === KeyTypes.Enter) {
|
|
2922
|
+
if (!visible) {
|
|
2923
|
+
show();
|
|
2924
|
+
}
|
|
2925
|
+
else {
|
|
2926
|
+
hide();
|
|
2927
|
+
}
|
|
2928
|
+
}
|
|
2929
|
+
};
|
|
2930
|
+
React.useEffect(() => {
|
|
2931
|
+
if (isVisible) {
|
|
2932
|
+
show();
|
|
2933
|
+
}
|
|
2934
|
+
else {
|
|
2935
|
+
hide();
|
|
2936
|
+
}
|
|
2937
|
+
}, [isVisible]);
|
|
2938
|
+
const show = () => {
|
|
2939
|
+
setVisible(true);
|
|
2940
|
+
};
|
|
2941
|
+
const hide = () => {
|
|
2942
|
+
setVisible(false);
|
|
2943
|
+
};
|
|
2944
|
+
const positionModifiers = {
|
|
2945
|
+
top: styles$1.modifiers.top,
|
|
2946
|
+
bottom: styles$1.modifiers.bottom,
|
|
2947
|
+
left: styles$1.modifiers.left,
|
|
2948
|
+
right: styles$1.modifiers.right,
|
|
2949
|
+
'top-start': styles$1.modifiers.topLeft,
|
|
2950
|
+
'top-end': styles$1.modifiers.topRight,
|
|
2951
|
+
'bottom-start': styles$1.modifiers.bottomLeft,
|
|
2952
|
+
'bottom-end': styles$1.modifiers.bottomRight,
|
|
2953
|
+
'left-start': styles$1.modifiers.leftTop,
|
|
2954
|
+
'left-end': styles$1.modifiers.leftBottom,
|
|
2955
|
+
'right-start': styles$1.modifiers.rightTop,
|
|
2956
|
+
'right-end': styles$1.modifiers.rightBottom
|
|
2957
|
+
};
|
|
2958
|
+
const hasCustomMaxWidth = maxWidth !== c_tooltip_MaxWidth.value;
|
|
2959
|
+
const content = (React.createElement("div", Object.assign({ "aria-live": ariaLive, className: css(styles$1.tooltip, className), role: "tooltip", id: id, style: {
|
|
2960
|
+
maxWidth: hasCustomMaxWidth ? maxWidth : null
|
|
2961
|
+
}, ref: popperRef }, rest),
|
|
2962
|
+
React.createElement(TooltipArrow, null),
|
|
2963
|
+
React.createElement(TooltipContent, { isLeftAligned: isContentLeftAligned }, bodyContent)));
|
|
2964
|
+
const onDocumentClick = (event, triggerElement) => {
|
|
2965
|
+
// event.currentTarget = document
|
|
2966
|
+
// event.target could be triggerElement or something else
|
|
2967
|
+
{
|
|
2968
|
+
// hide on inside the toggle as well as on outside clicks
|
|
2969
|
+
if (visible) {
|
|
2970
|
+
hide();
|
|
2971
|
+
}
|
|
2972
|
+
else if (event.target === triggerElement) {
|
|
2973
|
+
show();
|
|
2974
|
+
}
|
|
2975
|
+
}
|
|
2976
|
+
};
|
|
2977
|
+
const addAriaToTrigger = () => {
|
|
2978
|
+
if (aria === 'describedby' && children && children.props && !children.props['aria-describedby']) {
|
|
2979
|
+
return React.cloneElement(children, { 'aria-describedby': id });
|
|
2980
|
+
}
|
|
2981
|
+
else if (aria === 'labelledby' && children.props && !children.props['aria-labelledby']) {
|
|
2982
|
+
return React.cloneElement(children, { 'aria-labelledby': id });
|
|
2983
|
+
}
|
|
2984
|
+
return children;
|
|
2985
|
+
};
|
|
2986
|
+
return (React.createElement(Popper, { trigger: aria !== 'none' && visible ? addAriaToTrigger() : children, triggerRef: triggerRef, popper: content, popperRef: popperRef, minWidth: minWidth !== undefined ? minWidth : 'revert', appendTo: appendTo, isVisible: visible, positionModifiers: positionModifiers, distance: distance, placement: position, onMouseEnter: triggerOnMouseenter && show, onMouseLeave: triggerOnMouseenter && hide, onPopperMouseEnter: triggerOnMouseenter && show, onPopperMouseLeave: triggerOnMouseenter && hide, onFocus: triggerOnFocus && show, onBlur: triggerOnFocus && hide, onDocumentClick: triggerOnClick && onDocumentClick, onDocumentKeyDown: triggerManually ? null : onDocumentKeyDown, onTriggerEnter: triggerManually ? null : onTriggerEnter, enableFlip: enableFlip, zIndex: zIndex, flipBehavior: flipBehavior, animationDuration: animationDuration, entryDelay: entryDelay, exitDelay: exitDelay, onHidden: onTooltipHidden }));
|
|
2987
|
+
};
|
|
2988
|
+
Tooltip.displayName = 'Tooltip';
|
|
2989
|
+
|
|
2990
|
+
const AngleRightIconConfig = {
|
|
2991
|
+
name: 'AngleRightIcon',
|
|
2992
|
+
height: 512,
|
|
2993
|
+
width: 256,
|
|
2994
|
+
svgPath: 'M224.3 273l-136 136c-9.4 9.4-24.6 9.4-33.9 0l-22.6-22.6c-9.4-9.4-9.4-24.6 0-33.9l96.4-96.4-96.4-96.4c-9.4-9.4-9.4-24.6 0-33.9L54.3 103c9.4-9.4 24.6-9.4 33.9 0l136 136c9.5 9.4 9.5 24.6.1 34z',
|
|
2995
|
+
yOffset: 0,
|
|
2996
|
+
xOffset: 0,
|
|
2997
|
+
};
|
|
2998
|
+
|
|
2999
|
+
const AngleRightIcon = createIcon(AngleRightIconConfig);
|
|
3000
|
+
|
|
3001
|
+
const breadcrumbStyles = {
|
|
3002
|
+
"breadcrumbLink": "pf-v6-c-breadcrumb__link"};
|
|
3003
|
+
|
|
3004
|
+
const menuStyles = {
|
|
3005
|
+
"divider": "pf-v6-c-divider",
|
|
3006
|
+
"menu": "pf-v6-c-menu",
|
|
3007
|
+
"menuContent": "pf-v6-c-menu__content",
|
|
3008
|
+
"menuGroup": "pf-v6-c-menu__group",
|
|
3009
|
+
"menuGroupTitle": "pf-v6-c-menu__group-title",
|
|
3010
|
+
"menuItem": "pf-v6-c-menu__item",
|
|
3011
|
+
"menuItemAction": "pf-v6-c-menu__item-action",
|
|
3012
|
+
"menuItemCheck": "pf-v6-c-menu__item-check",
|
|
3013
|
+
"menuItemDescription": "pf-v6-c-menu__item-description",
|
|
3014
|
+
"menuItemExternalIcon": "pf-v6-c-menu__item-external-icon",
|
|
3015
|
+
"menuItemIcon": "pf-v6-c-menu__item-icon",
|
|
3016
|
+
"menuItemMain": "pf-v6-c-menu__item-main",
|
|
3017
|
+
"menuItemSelectIcon": "pf-v6-c-menu__item-select-icon",
|
|
3018
|
+
"menuItemText": "pf-v6-c-menu__item-text",
|
|
3019
|
+
"menuItemToggleIcon": "pf-v6-c-menu__item-toggle-icon",
|
|
3020
|
+
"menuList": "pf-v6-c-menu__list",
|
|
3021
|
+
"menuListItem": "pf-v6-c-menu__list-item",
|
|
3022
|
+
"menuSearch": "pf-v6-c-menu__search",
|
|
3023
|
+
"modifiers": {
|
|
3024
|
+
"disabled": "pf-m-disabled",
|
|
3025
|
+
"ariaDisabled": "pf-m-aria-disabled",
|
|
3026
|
+
"flyout": "pf-m-flyout",
|
|
3027
|
+
"left": "pf-m-left",
|
|
3028
|
+
"drilldown": "pf-m-drilldown",
|
|
3029
|
+
"drilledIn": "pf-m-drilled-in",
|
|
3030
|
+
"currentPath": "pf-m-current-path",
|
|
3031
|
+
"plain": "pf-m-plain",
|
|
3032
|
+
"scrollable": "pf-m-scrollable",
|
|
3033
|
+
"load": "pf-m-load",
|
|
3034
|
+
"loading": "pf-m-loading",
|
|
3035
|
+
"danger": "pf-m-danger",
|
|
3036
|
+
"selected": "pf-m-selected",
|
|
3037
|
+
"favorited": "pf-m-favorited"
|
|
3038
|
+
}
|
|
3039
|
+
};
|
|
3040
|
+
|
|
3041
|
+
const MenuContext = React.createContext({
|
|
3042
|
+
menuId: null,
|
|
3043
|
+
parentMenu: null,
|
|
3044
|
+
onActionClick: () => null,
|
|
3045
|
+
onSelect: () => null,
|
|
3046
|
+
activeItemId: null,
|
|
3047
|
+
selected: null,
|
|
3048
|
+
drilledInMenus: [],
|
|
3049
|
+
drilldownItemPath: [],
|
|
3050
|
+
onDrillIn: null,
|
|
3051
|
+
onDrillOut: null,
|
|
3052
|
+
onGetMenuHeight: () => null,
|
|
3053
|
+
flyoutRef: null,
|
|
3054
|
+
setFlyoutRef: () => null,
|
|
3055
|
+
disableHover: false,
|
|
3056
|
+
role: 'menu'
|
|
3057
|
+
});
|
|
3058
|
+
const MenuItemContext = React.createContext({
|
|
3059
|
+
itemId: null,
|
|
3060
|
+
isDisabled: false
|
|
3061
|
+
});
|
|
3062
|
+
|
|
3063
|
+
class MenuBase extends React.Component {
|
|
3064
|
+
constructor(props) {
|
|
3065
|
+
super(props);
|
|
3066
|
+
this.menuRef = React.createRef();
|
|
3067
|
+
this.activeMenu = null;
|
|
3068
|
+
this.state = {
|
|
3069
|
+
ouiaStateId: getDefaultOUIAId(Menu.displayName),
|
|
3070
|
+
transitionMoveTarget: null,
|
|
3071
|
+
flyoutRef: null,
|
|
3072
|
+
disableHover: false,
|
|
3073
|
+
currentDrilldownMenuId: this.props.id
|
|
3074
|
+
};
|
|
3075
|
+
this.handleDrilldownTransition = (event) => {
|
|
3076
|
+
const current = this.menuRef.current;
|
|
3077
|
+
if (!current ||
|
|
3078
|
+
(current !== event.target.closest(`.${menuStyles.menu}`) &&
|
|
3079
|
+
!Array.from(current.getElementsByClassName(menuStyles.menu)).includes(event.target.closest(`.${menuStyles.menu}`)))) {
|
|
3080
|
+
return;
|
|
3081
|
+
}
|
|
3082
|
+
if (this.state.transitionMoveTarget) {
|
|
3083
|
+
this.state.transitionMoveTarget.focus();
|
|
3084
|
+
this.setState({ transitionMoveTarget: null });
|
|
3085
|
+
}
|
|
3086
|
+
else {
|
|
3087
|
+
const nextMenu = current.querySelector('#' + this.props.activeMenu) || current || null;
|
|
3088
|
+
const nextMenuLists = nextMenu.getElementsByTagName('UL');
|
|
3089
|
+
if (nextMenuLists.length === 0) {
|
|
3090
|
+
return;
|
|
3091
|
+
}
|
|
3092
|
+
const nextMenuChildren = Array.from(nextMenuLists[0].children);
|
|
3093
|
+
if (!this.state.currentDrilldownMenuId || nextMenu.id !== this.state.currentDrilldownMenuId) {
|
|
3094
|
+
this.setState({ currentDrilldownMenuId: nextMenu.id });
|
|
3095
|
+
}
|
|
3096
|
+
else {
|
|
3097
|
+
// if the drilldown transition ends on the same menu, do not focus the first item
|
|
3098
|
+
return;
|
|
3099
|
+
}
|
|
3100
|
+
const nextTarget = nextMenuChildren.filter((el) => !(el.classList.contains('pf-m-disabled') || el.classList.contains(menuStyles.divider)))[0].firstChild;
|
|
3101
|
+
nextTarget.focus();
|
|
3102
|
+
nextTarget.tabIndex = 0;
|
|
3103
|
+
}
|
|
3104
|
+
};
|
|
3105
|
+
this.handleExtraKeys = (event) => {
|
|
3106
|
+
const isDrilldown = this.props.containsDrilldown;
|
|
3107
|
+
const activeElement = document.activeElement;
|
|
3108
|
+
if (event.target.closest(`.${menuStyles.menu}`) !== this.activeMenu &&
|
|
3109
|
+
!event.target.classList.contains(breadcrumbStyles.breadcrumbLink)) {
|
|
3110
|
+
this.activeMenu = event.target.closest(`.${menuStyles.menu}`);
|
|
3111
|
+
this.setState({ disableHover: true });
|
|
3112
|
+
}
|
|
3113
|
+
if (event.target.tagName === 'INPUT') {
|
|
3114
|
+
return;
|
|
3115
|
+
}
|
|
3116
|
+
const parentMenu = this.activeMenu;
|
|
3117
|
+
const key = event.key;
|
|
3118
|
+
const isFromBreadcrumb = activeElement.classList.contains(breadcrumbStyles.breadcrumbLink);
|
|
3119
|
+
if (key === ' ' || key === 'Enter') {
|
|
3120
|
+
event.preventDefault();
|
|
3121
|
+
if (isDrilldown && !isFromBreadcrumb) {
|
|
3122
|
+
const isDrillingOut = activeElement.closest('li').classList.contains('pf-m-current-path');
|
|
3123
|
+
if (isDrillingOut && parentMenu.parentElement.tagName === 'LI') {
|
|
3124
|
+
activeElement.tabIndex = -1;
|
|
3125
|
+
parentMenu.parentElement.firstChild.tabIndex = 0;
|
|
3126
|
+
this.setState({ transitionMoveTarget: parentMenu.parentElement.firstChild });
|
|
3127
|
+
}
|
|
3128
|
+
else {
|
|
3129
|
+
if (activeElement.nextElementSibling && activeElement.nextElementSibling.classList.contains(menuStyles.menu)) {
|
|
3130
|
+
const childItems = Array.from(activeElement.nextElementSibling.getElementsByTagName('UL')[0].children).filter((el) => !(el.classList.contains('pf-m-disabled') || el.classList.contains(menuStyles.divider)));
|
|
3131
|
+
activeElement.tabIndex = -1;
|
|
3132
|
+
childItems[0].firstChild.tabIndex = 0;
|
|
3133
|
+
this.setState({ transitionMoveTarget: childItems[0].firstChild });
|
|
3134
|
+
}
|
|
3135
|
+
}
|
|
3136
|
+
}
|
|
3137
|
+
document.activeElement.click();
|
|
3138
|
+
}
|
|
3139
|
+
};
|
|
3140
|
+
this.createNavigableElements = () => {
|
|
3141
|
+
const isDrilldown = this.props.containsDrilldown;
|
|
3142
|
+
if (isDrilldown) {
|
|
3143
|
+
return this.activeMenu
|
|
3144
|
+
? Array.from(this.activeMenu.getElementsByTagName('UL')[0].children).filter((el) => !(el.classList.contains('pf-m-disabled') || el.classList.contains(menuStyles.divider)))
|
|
3145
|
+
: [];
|
|
3146
|
+
}
|
|
3147
|
+
else {
|
|
3148
|
+
return this.menuRef.current
|
|
3149
|
+
? Array.from(this.menuRef.current.getElementsByTagName('LI')).filter((el) => !(el.classList.contains('pf-m-disabled') || el.classList.contains(menuStyles.divider)))
|
|
3150
|
+
: [];
|
|
3151
|
+
}
|
|
3152
|
+
};
|
|
3153
|
+
if (props.innerRef) {
|
|
3154
|
+
this.menuRef = props.innerRef;
|
|
3155
|
+
}
|
|
3156
|
+
}
|
|
3157
|
+
allowTabFirstItem() {
|
|
3158
|
+
// Allow tabbing to first menu item
|
|
3159
|
+
const current = this.menuRef.current;
|
|
3160
|
+
if (current) {
|
|
3161
|
+
const first = current.querySelector('ul button:not(:disabled), ul a:not(:disabled)');
|
|
3162
|
+
if (first) {
|
|
3163
|
+
first.tabIndex = 0;
|
|
3164
|
+
}
|
|
3165
|
+
}
|
|
3166
|
+
}
|
|
3167
|
+
componentDidMount() {
|
|
3168
|
+
if (this.context) {
|
|
3169
|
+
this.setState({ disableHover: this.context.disableHover });
|
|
3170
|
+
}
|
|
3171
|
+
if (canUseDOM && this.props.containsDrilldown) {
|
|
3172
|
+
window.addEventListener('transitionend', this.props.isRootMenu ? this.handleDrilldownTransition : null);
|
|
3173
|
+
}
|
|
3174
|
+
this.allowTabFirstItem();
|
|
3175
|
+
}
|
|
3176
|
+
componentWillUnmount() {
|
|
3177
|
+
if (canUseDOM && this.props.containsDrilldown) {
|
|
3178
|
+
window.removeEventListener('transitionend', this.handleDrilldownTransition);
|
|
3179
|
+
}
|
|
3180
|
+
}
|
|
3181
|
+
componentDidUpdate(prevProps) {
|
|
3182
|
+
if (prevProps.children !== this.props.children) {
|
|
3183
|
+
this.allowTabFirstItem();
|
|
3184
|
+
}
|
|
3185
|
+
}
|
|
3186
|
+
render() {
|
|
3187
|
+
const _a = this.props, { id, children, className, onSelect, selected = null, onActionClick, ouiaId, ouiaSafe, containsFlyout, containsDrilldown, isMenuDrilledIn, isPlain, isScrollable, drilldownItemPath, drilledInMenus, onDrillIn, onDrillOut, onGetMenuHeight, parentMenu = null, activeItemId = null,
|
|
3188
|
+
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
3189
|
+
innerRef, isRootMenu, activeMenu, role, isNavFlyout } = _a,
|
|
3190
|
+
/* eslint-enable @typescript-eslint/no-unused-vars */
|
|
3191
|
+
props = __rest(_a, ["id", "children", "className", "onSelect", "selected", "onActionClick", "ouiaId", "ouiaSafe", "containsFlyout", "containsDrilldown", "isMenuDrilledIn", "isPlain", "isScrollable", "drilldownItemPath", "drilledInMenus", "onDrillIn", "onDrillOut", "onGetMenuHeight", "parentMenu", "activeItemId", "innerRef", "isRootMenu", "activeMenu", "role", "isNavFlyout"]);
|
|
3192
|
+
const _isMenuDrilledIn = isMenuDrilledIn || (drilledInMenus && drilledInMenus.includes(id)) || false;
|
|
3193
|
+
return (React.createElement(MenuContext.Provider, { value: {
|
|
3194
|
+
menuId: id,
|
|
3195
|
+
parentMenu: parentMenu || id,
|
|
3196
|
+
onSelect,
|
|
3197
|
+
onActionClick,
|
|
3198
|
+
activeItemId,
|
|
3199
|
+
selected,
|
|
3200
|
+
drilledInMenus,
|
|
3201
|
+
drilldownItemPath,
|
|
3202
|
+
onDrillIn,
|
|
3203
|
+
onDrillOut,
|
|
3204
|
+
onGetMenuHeight,
|
|
3205
|
+
flyoutRef: this.state.flyoutRef,
|
|
3206
|
+
setFlyoutRef: (flyoutRef) => this.setState({ flyoutRef }),
|
|
3207
|
+
disableHover: this.state.disableHover,
|
|
3208
|
+
role
|
|
3209
|
+
} },
|
|
3210
|
+
isRootMenu && (React.createElement(KeyboardHandler, { containerRef: this.menuRef || null, additionalKeyHandler: this.handleExtraKeys, createNavigableElements: this.createNavigableElements, isActiveElement: (element) => document.activeElement.closest('li') === element || // if element is a basic MenuItem
|
|
3211
|
+
document.activeElement.parentElement === element ||
|
|
3212
|
+
document.activeElement.closest(`.${menuStyles.menuSearch}`) === element || // if element is a MenuSearch
|
|
3213
|
+
(document.activeElement.closest('ol') && document.activeElement.closest('ol').firstChild === element), getFocusableElement: (navigableElement) => {
|
|
3214
|
+
var _a, _b;
|
|
3215
|
+
return ((navigableElement === null || navigableElement === void 0 ? void 0 : navigableElement.tagName) === 'DIV' && navigableElement.querySelector('input')) || // for MenuSearchInput
|
|
3216
|
+
(((_a = navigableElement.firstChild) === null || _a === void 0 ? void 0 : _a.tagName) === 'LABEL' &&
|
|
3217
|
+
navigableElement.querySelector('input')) || // for MenuItem checkboxes
|
|
3218
|
+
(((_b = navigableElement.firstChild) === null || _b === void 0 ? void 0 : _b.tagName) === 'DIV' &&
|
|
3219
|
+
navigableElement.querySelector('a, button, input')) || // For aria-disabled element that is rendered inside a div with "display: contents" styling
|
|
3220
|
+
navigableElement.firstChild;
|
|
3221
|
+
}, noHorizontalArrowHandling: document.activeElement &&
|
|
3222
|
+
(document.activeElement.classList.contains(breadcrumbStyles.breadcrumbLink) ||
|
|
3223
|
+
document.activeElement.tagName === 'INPUT'), noEnterHandling: true, noSpaceHandling: true })),
|
|
3224
|
+
React.createElement("div", Object.assign({ id: id, className: css(menuStyles.menu, isPlain && menuStyles.modifiers.plain, isScrollable && menuStyles.modifiers.scrollable, containsFlyout && menuStyles.modifiers.flyout, isNavFlyout && 'pf-m-nav', containsDrilldown && menuStyles.modifiers.drilldown, _isMenuDrilledIn && menuStyles.modifiers.drilledIn, className), ref: this.menuRef }, getOUIAProps(Menu.displayName, ouiaId !== undefined ? ouiaId : this.state.ouiaStateId, ouiaSafe), props), children)));
|
|
3225
|
+
}
|
|
3226
|
+
}
|
|
3227
|
+
MenuBase.displayName = 'Menu';
|
|
3228
|
+
MenuBase.contextType = MenuContext;
|
|
3229
|
+
MenuBase.defaultProps = {
|
|
3230
|
+
ouiaSafe: true,
|
|
3231
|
+
isRootMenu: true,
|
|
3232
|
+
isPlain: false,
|
|
3233
|
+
isScrollable: false,
|
|
3234
|
+
role: 'menu'
|
|
3235
|
+
};
|
|
3236
|
+
const Menu = React.forwardRef((props, ref) => (React.createElement(MenuBase, Object.assign({}, props, { innerRef: ref }))));
|
|
3237
|
+
Menu.displayName = 'Menu';
|
|
3238
|
+
|
|
3239
|
+
const c_menu__content_Height = {
|
|
3240
|
+
"name": "--pf-v6-c-menu__content--Height"};
|
|
3241
|
+
|
|
3242
|
+
const c_menu__content_MaxHeight = {
|
|
3243
|
+
"name": "--pf-v6-c-menu__content--MaxHeight"};
|
|
3244
|
+
|
|
3245
|
+
const MenuContent = React.forwardRef((props, ref) => {
|
|
3246
|
+
const { getHeight, children, menuHeight, maxMenuHeight } = props, rest = __rest(props, ["getHeight", "children", "menuHeight", "maxMenuHeight"]);
|
|
3247
|
+
const menuContentRef = React.createRef();
|
|
3248
|
+
const refCallback = (el, menuId, onGetMenuHeight) => {
|
|
3249
|
+
if (el) {
|
|
3250
|
+
let clientHeight = el.clientHeight;
|
|
3251
|
+
// if this menu is a submenu, we need to account for the root menu list's padding and root menu content's border.
|
|
3252
|
+
let rootMenuList = null;
|
|
3253
|
+
let parentEl = el.closest(`.${menuStyles.menuList}`);
|
|
3254
|
+
while (parentEl !== null && parentEl.nodeType === 1) {
|
|
3255
|
+
if (parentEl.classList.contains(menuStyles.menuList)) {
|
|
3256
|
+
rootMenuList = parentEl;
|
|
3257
|
+
}
|
|
3258
|
+
parentEl = parentEl.parentElement;
|
|
3259
|
+
}
|
|
3260
|
+
if (rootMenuList) {
|
|
3261
|
+
const rootMenuListStyles = getComputedStyle(rootMenuList);
|
|
3262
|
+
const rootMenuListPaddingOffset = parseFloat(rootMenuListStyles.getPropertyValue('padding-top').replace(/px/g, '')) +
|
|
3263
|
+
parseFloat(rootMenuListStyles.getPropertyValue('padding-bottom').replace(/px/g, '')) +
|
|
3264
|
+
parseFloat(getComputedStyle(rootMenuList.parentElement).getPropertyValue('border-bottom-width').replace(/px/g, ''));
|
|
3265
|
+
clientHeight = clientHeight + rootMenuListPaddingOffset;
|
|
3266
|
+
}
|
|
3267
|
+
onGetMenuHeight && onGetMenuHeight(menuId, clientHeight);
|
|
3268
|
+
getHeight && getHeight(clientHeight.toString());
|
|
3269
|
+
}
|
|
3270
|
+
return ref || menuContentRef;
|
|
3271
|
+
};
|
|
3272
|
+
return (React.createElement(MenuContext.Consumer, null, ({ menuId, onGetMenuHeight }) => (React.createElement("div", Object.assign({}, rest, { className: css(menuStyles.menuContent, props.className), ref: (el) => refCallback(el, menuId, onGetMenuHeight), style: Object.assign(Object.assign({}, (menuHeight && { [c_menu__content_Height.name]: menuHeight })), (maxMenuHeight && { [c_menu__content_MaxHeight.name]: maxMenuHeight })) }), children))));
|
|
3273
|
+
});
|
|
3274
|
+
MenuContent.displayName = 'MenuContent';
|
|
3275
|
+
|
|
3276
|
+
const c_menu_m_flyout__menu_top_offset = {
|
|
3277
|
+
"name": "--pf-v6-c-menu--m-flyout__menu--top-offset"};
|
|
3278
|
+
|
|
3279
|
+
const c_menu_m_flyout__menu_m_left_right_offset = {
|
|
3280
|
+
"name": "--pf-v6-c-menu--m-flyout__menu--m-left--right-offset"};
|
|
3281
|
+
|
|
3282
|
+
const c_menu_m_flyout__menu_left_offset = {
|
|
3283
|
+
"name": "--pf-v6-c-menu--m-flyout__menu--left-offset"};
|
|
3284
|
+
|
|
3285
|
+
const ExternalLinkAltIconConfig = {
|
|
3286
|
+
name: 'ExternalLinkAltIcon',
|
|
3287
|
+
height: 512,
|
|
3288
|
+
width: 512,
|
|
3289
|
+
svgPath: 'M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z',
|
|
3290
|
+
yOffset: 0,
|
|
3291
|
+
xOffset: 0,
|
|
3292
|
+
};
|
|
3293
|
+
|
|
3294
|
+
const ExternalLinkAltIcon = createIcon(ExternalLinkAltIconConfig);
|
|
3295
|
+
|
|
3296
|
+
const AngleLeftIconConfig = {
|
|
3297
|
+
name: 'AngleLeftIcon',
|
|
3298
|
+
height: 512,
|
|
3299
|
+
width: 256,
|
|
3300
|
+
svgPath: 'M31.7 239l136-136c9.4-9.4 24.6-9.4 33.9 0l22.6 22.6c9.4 9.4 9.4 24.6 0 33.9L127.9 256l96.4 96.4c9.4 9.4 9.4 24.6 0 33.9L201.7 409c-9.4 9.4-24.6 9.4-33.9 0l-136-136c-9.5-9.4-9.5-24.6-.1-34z',
|
|
3301
|
+
yOffset: 0,
|
|
3302
|
+
xOffset: 0,
|
|
3303
|
+
};
|
|
3304
|
+
|
|
3305
|
+
const AngleLeftIcon = createIcon(AngleLeftIconConfig);
|
|
3306
|
+
|
|
3307
|
+
const CheckIconConfig = {
|
|
3308
|
+
name: 'CheckIcon',
|
|
3309
|
+
height: 512,
|
|
3310
|
+
width: 512,
|
|
3311
|
+
svgPath: 'M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z',
|
|
3312
|
+
yOffset: 0,
|
|
3313
|
+
xOffset: 0,
|
|
3314
|
+
};
|
|
3315
|
+
|
|
3316
|
+
const CheckIcon = createIcon(CheckIconConfig);
|
|
3317
|
+
|
|
3318
|
+
const checkStyles = {
|
|
3319
|
+
"check": "pf-v6-c-check",
|
|
3320
|
+
"checkBody": "pf-v6-c-check__body",
|
|
3321
|
+
"checkDescription": "pf-v6-c-check__description",
|
|
3322
|
+
"checkInput": "pf-v6-c-check__input",
|
|
3323
|
+
"checkLabel": "pf-v6-c-check__label",
|
|
3324
|
+
"checkLabelRequired": "pf-v6-c-check__label-required",
|
|
3325
|
+
"modifiers": {
|
|
3326
|
+
"standalone": "pf-m-standalone",
|
|
3327
|
+
"disabled": "pf-m-disabled"
|
|
3328
|
+
}
|
|
3329
|
+
};
|
|
3330
|
+
|
|
3331
|
+
// tslint:disable-next-line:no-empty
|
|
3332
|
+
const defaultOnChange = () => { };
|
|
3333
|
+
class Checkbox extends React.Component {
|
|
3334
|
+
constructor(props) {
|
|
3335
|
+
super(props);
|
|
3336
|
+
this.handleChange = (event) => {
|
|
3337
|
+
this.props.onChange(event, event.currentTarget.checked);
|
|
3338
|
+
};
|
|
3339
|
+
this.state = {
|
|
3340
|
+
ouiaStateId: getDefaultOUIAId(Checkbox.displayName)
|
|
3341
|
+
};
|
|
3342
|
+
}
|
|
3343
|
+
render() {
|
|
3344
|
+
const _a = this.props, { 'aria-label': ariaLabel, className, inputClassName, onChange, isLabelWrapped, labelPosition = 'end', isValid, isDisabled, isRequired, isChecked, label, checked, defaultChecked, description, body, ouiaId, ouiaSafe, component } = _a, props = __rest(_a, ['aria-label', "className", "inputClassName", "onChange", "isLabelWrapped", "labelPosition", "isValid", "isDisabled", "isRequired", "isChecked", "label", "checked", "defaultChecked", "description", "body", "ouiaId", "ouiaSafe", "component"]);
|
|
3345
|
+
if (!props.id) {
|
|
3346
|
+
// eslint-disable-next-line no-console
|
|
3347
|
+
console.error('Checkbox:', 'id is required to make input accessible');
|
|
3348
|
+
}
|
|
3349
|
+
const checkedProps = {};
|
|
3350
|
+
if ([true, false].includes(checked) || isChecked === true) {
|
|
3351
|
+
checkedProps.checked = checked || isChecked;
|
|
3352
|
+
}
|
|
3353
|
+
if (onChange !== defaultOnChange) {
|
|
3354
|
+
checkedProps.checked = isChecked;
|
|
3355
|
+
}
|
|
3356
|
+
if ([false, true].includes(defaultChecked)) {
|
|
3357
|
+
checkedProps.defaultChecked = defaultChecked;
|
|
3358
|
+
}
|
|
3359
|
+
const inputRendered = (React.createElement("input", Object.assign({}, props, { className: css(checkStyles.checkInput, inputClassName), type: "checkbox", onChange: this.handleChange, "aria-invalid": !isValid, "aria-label": ariaLabel, disabled: isDisabled, required: isRequired, ref: (elem) => elem && (elem.indeterminate = isChecked === null) }, checkedProps, getOUIAProps(Checkbox.displayName, ouiaId !== undefined ? ouiaId : this.state.ouiaStateId, ouiaSafe))));
|
|
3360
|
+
const wrapWithLabel = (isLabelWrapped && !component) || component === 'label';
|
|
3361
|
+
const Label = wrapWithLabel ? 'span' : 'label';
|
|
3362
|
+
const labelRendered = label ? (React.createElement(Label, { className: css(checkStyles.checkLabel, isDisabled && checkStyles.modifiers.disabled), htmlFor: !wrapWithLabel ? props.id : undefined },
|
|
3363
|
+
label,
|
|
3364
|
+
isRequired && (React.createElement("span", { className: css(checkStyles.checkLabelRequired), "aria-hidden": "true" }, ASTERISK)))) : null;
|
|
3365
|
+
const Component = component !== null && component !== void 0 ? component : (wrapWithLabel ? 'label' : 'div');
|
|
3366
|
+
checkedProps.checked = checkedProps.checked === null ? false : checkedProps.checked;
|
|
3367
|
+
return (React.createElement(Component, { className: css(checkStyles.check, !label && checkStyles.modifiers.standalone, className), htmlFor: wrapWithLabel ? props.id : undefined },
|
|
3368
|
+
labelPosition === 'start' ? (React.createElement(React.Fragment, null,
|
|
3369
|
+
labelRendered,
|
|
3370
|
+
inputRendered)) : (React.createElement(React.Fragment, null,
|
|
3371
|
+
inputRendered,
|
|
3372
|
+
labelRendered)),
|
|
3373
|
+
description && React.createElement("span", { className: css(checkStyles.checkDescription) }, description),
|
|
3374
|
+
body && React.createElement("span", { className: css(checkStyles.checkBody) }, body)));
|
|
3375
|
+
}
|
|
3376
|
+
}
|
|
3377
|
+
Checkbox.displayName = 'Checkbox';
|
|
3378
|
+
Checkbox.defaultProps = {
|
|
3379
|
+
className: '',
|
|
3380
|
+
isLabelWrapped: false,
|
|
3381
|
+
isValid: true,
|
|
3382
|
+
isDisabled: false,
|
|
3383
|
+
isRequired: false,
|
|
3384
|
+
isChecked: false,
|
|
3385
|
+
onChange: defaultOnChange,
|
|
3386
|
+
ouiaSafe: true
|
|
3387
|
+
};
|
|
3388
|
+
|
|
3389
|
+
const StarIconConfig = {
|
|
3390
|
+
name: 'StarIcon',
|
|
3391
|
+
height: 512,
|
|
3392
|
+
width: 576,
|
|
3393
|
+
svgPath: 'M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z',
|
|
3394
|
+
yOffset: 0,
|
|
3395
|
+
xOffset: 0,
|
|
3396
|
+
};
|
|
3397
|
+
|
|
3398
|
+
const StarIcon = createIcon(StarIconConfig);
|
|
3399
|
+
|
|
3400
|
+
const MenuItemActionBase = (_a) => {
|
|
3401
|
+
var { className, icon, onClick, 'aria-label': ariaLabel, isFavorited = null, isDisabled, actionId, innerRef } = _a, props = __rest(_a, ["className", "icon", "onClick", 'aria-label', "isFavorited", "isDisabled", "actionId", "innerRef"]);
|
|
3402
|
+
return (React.createElement(MenuContext.Consumer, null, ({ onActionClick }) => (React.createElement(MenuItemContext.Consumer, null, ({ itemId, isDisabled: isDisabledContext }) => {
|
|
3403
|
+
const onClickButton = (event) => {
|
|
3404
|
+
// event specified on the MenuItemAction
|
|
3405
|
+
onClick && onClick(event);
|
|
3406
|
+
// event specified on the Menu
|
|
3407
|
+
onActionClick && onActionClick(event, itemId, actionId);
|
|
3408
|
+
};
|
|
3409
|
+
return (React.createElement("div", Object.assign({ className: css(menuStyles.menuItemAction, isFavorited !== null && 'pf-m-favorite', isFavorited && menuStyles.modifiers.favorited, className) }, props),
|
|
3410
|
+
React.createElement(Button, { "aria-label": ariaLabel, onClick: onClickButton, ref: innerRef, role: "menuitem", variant: "plain", tabIndex: -1, isDisabled: isDisabled || isDisabledContext, icon: icon === 'favorites' || isFavorited !== null ? React.createElement(StarIcon, { "aria-hidden": true }) : icon })));
|
|
3411
|
+
}))));
|
|
3412
|
+
};
|
|
3413
|
+
const MenuItemAction = React.forwardRef((props, ref) => (React.createElement(MenuItemActionBase, Object.assign({}, props, { innerRef: ref }))));
|
|
3414
|
+
MenuItemAction.displayName = 'MenuItemAction';
|
|
3415
|
+
|
|
3416
|
+
const FlyoutContext = React.createContext({
|
|
3417
|
+
direction: 'right'
|
|
3418
|
+
});
|
|
3419
|
+
const MenuItemBase = (_a) => {
|
|
3420
|
+
var { children, className, itemId = null, to, hasCheckbox = false, isActive = null, isFavorited = null, isLoadButton = false, isLoading = false, flyoutMenu, direction, description = null, onClick = () => { }, component = 'button', isDisabled = false, isAriaDisabled = false, isExternalLink = false, isSelected = null, isFocused, isDanger = false, icon, actions, onShowFlyout, drilldownMenu, isOnPath, innerRef, id, 'aria-label': ariaLabel, tooltipProps, rel, target, download } = _a, props = __rest(_a, ["children", "className", "itemId", "to", "hasCheckbox", "isActive", "isFavorited", "isLoadButton", "isLoading", "flyoutMenu", "direction", "description", "onClick", "component", "isDisabled", "isAriaDisabled", "isExternalLink", "isSelected", "isFocused", "isDanger", "icon", "actions", "onShowFlyout", "drilldownMenu", "isOnPath", "innerRef", "id", 'aria-label', "tooltipProps", "rel", "target", "download"]);
|
|
3421
|
+
const { menuId, parentMenu, onSelect, onActionClick, activeItemId, selected, drilldownItemPath, onDrillIn, onDrillOut, flyoutRef, setFlyoutRef, disableHover, role: menuRole } = React.useContext(MenuContext);
|
|
3422
|
+
let Component = (to ? 'a' : component);
|
|
3423
|
+
if (hasCheckbox && !to) {
|
|
3424
|
+
Component = 'label';
|
|
3425
|
+
}
|
|
3426
|
+
const [flyoutTarget, setFlyoutTarget] = React.useState(null);
|
|
3427
|
+
const flyoutContext = React.useContext(FlyoutContext);
|
|
3428
|
+
const [flyoutXDirection, setFlyoutXDirection] = React.useState(flyoutContext.direction);
|
|
3429
|
+
const ref = React.useRef();
|
|
3430
|
+
const flyoutVisible = ref === flyoutRef;
|
|
3431
|
+
const hasFlyout = flyoutMenu !== undefined;
|
|
3432
|
+
const showFlyout = (show) => {
|
|
3433
|
+
if (!flyoutVisible && show) {
|
|
3434
|
+
setFlyoutRef(ref);
|
|
3435
|
+
}
|
|
3436
|
+
else if (flyoutVisible && !show) {
|
|
3437
|
+
setFlyoutRef(null);
|
|
3438
|
+
}
|
|
3439
|
+
onShowFlyout && show && onShowFlyout();
|
|
3440
|
+
};
|
|
3441
|
+
useIsomorphicLayoutEffect(() => {
|
|
3442
|
+
if (hasFlyout && ref.current && canUseDOM) {
|
|
3443
|
+
const flyoutMenu = ref.current.lastElementChild;
|
|
3444
|
+
if (flyoutMenu && flyoutMenu.classList.contains(menuStyles.menu)) {
|
|
3445
|
+
const origin = ref.current.getClientRects()[0];
|
|
3446
|
+
const rect = flyoutMenu.getClientRects()[0];
|
|
3447
|
+
if (origin && rect) {
|
|
3448
|
+
const spaceLeftLeft = origin.x - rect.width;
|
|
3449
|
+
const spaceLeftRight = window.innerWidth - origin.x - origin.width - rect.width;
|
|
3450
|
+
let xDir = flyoutXDirection;
|
|
3451
|
+
if (spaceLeftRight < 0 && xDir !== 'left') {
|
|
3452
|
+
setFlyoutXDirection('left');
|
|
3453
|
+
xDir = 'left';
|
|
3454
|
+
}
|
|
3455
|
+
else if (spaceLeftLeft < 0 && xDir !== 'right') {
|
|
3456
|
+
setFlyoutXDirection('right');
|
|
3457
|
+
xDir = 'right';
|
|
3458
|
+
}
|
|
3459
|
+
let xOffset = 0;
|
|
3460
|
+
if (spaceLeftLeft < 0 && spaceLeftRight < 0) {
|
|
3461
|
+
xOffset = xDir === 'right' ? -spaceLeftRight : -spaceLeftLeft;
|
|
3462
|
+
}
|
|
3463
|
+
if (xDir === 'left') {
|
|
3464
|
+
flyoutMenu.classList.add(menuStyles.modifiers.left);
|
|
3465
|
+
flyoutMenu.style.setProperty(c_menu_m_flyout__menu_m_left_right_offset.name, `-${xOffset}px`);
|
|
3466
|
+
}
|
|
3467
|
+
else {
|
|
3468
|
+
flyoutMenu.style.setProperty(c_menu_m_flyout__menu_left_offset.name, `-${xOffset}px`);
|
|
3469
|
+
}
|
|
3470
|
+
const spaceLeftBot = window.innerHeight - origin.y - rect.height;
|
|
3471
|
+
const spaceLeftTop = window.innerHeight - rect.height;
|
|
3472
|
+
if (spaceLeftTop < 0 && spaceLeftBot < 0) ;
|
|
3473
|
+
else if (spaceLeftBot < 0) {
|
|
3474
|
+
flyoutMenu.style.setProperty(c_menu_m_flyout__menu_top_offset.name, `${spaceLeftBot}px`);
|
|
3475
|
+
}
|
|
3476
|
+
}
|
|
3477
|
+
}
|
|
3478
|
+
}
|
|
3479
|
+
}, [flyoutVisible, flyoutMenu]);
|
|
3480
|
+
React.useEffect(() => {
|
|
3481
|
+
setFlyoutXDirection(flyoutContext.direction);
|
|
3482
|
+
}, [flyoutContext]);
|
|
3483
|
+
React.useEffect(() => {
|
|
3484
|
+
if (flyoutTarget) {
|
|
3485
|
+
if (flyoutVisible) {
|
|
3486
|
+
const flyoutMenu = flyoutTarget.nextElementSibling;
|
|
3487
|
+
const flyoutItems = Array.from(flyoutMenu.getElementsByTagName('UL')[0].children).filter((el) => !(el.classList.contains('pf-m-disabled') || el.classList.contains(menuStyles.divider)));
|
|
3488
|
+
flyoutItems[0].firstChild.focus();
|
|
3489
|
+
}
|
|
3490
|
+
else {
|
|
3491
|
+
flyoutTarget.focus();
|
|
3492
|
+
}
|
|
3493
|
+
}
|
|
3494
|
+
}, [flyoutVisible, flyoutTarget]);
|
|
3495
|
+
const handleFlyout = (event) => {
|
|
3496
|
+
const key = event.key;
|
|
3497
|
+
const target = event.target;
|
|
3498
|
+
const type = event.type;
|
|
3499
|
+
if (key === ' ' || key === 'Enter' || key === 'ArrowRight' || type === 'click') {
|
|
3500
|
+
event.stopPropagation();
|
|
3501
|
+
event.preventDefault();
|
|
3502
|
+
if (!flyoutVisible) {
|
|
3503
|
+
showFlyout(true);
|
|
3504
|
+
setFlyoutTarget(target);
|
|
3505
|
+
}
|
|
3506
|
+
}
|
|
3507
|
+
if (key === 'Escape' || key === 'ArrowLeft') {
|
|
3508
|
+
if (flyoutVisible) {
|
|
3509
|
+
event.stopPropagation();
|
|
3510
|
+
showFlyout(false);
|
|
3511
|
+
}
|
|
3512
|
+
}
|
|
3513
|
+
};
|
|
3514
|
+
const onItemSelect = (event, onSelect) => {
|
|
3515
|
+
if (!isAriaDisabled) {
|
|
3516
|
+
// Trigger callback for Menu onSelect
|
|
3517
|
+
onSelect && onSelect(event, itemId);
|
|
3518
|
+
// Trigger callback for item onClick
|
|
3519
|
+
onClick && onClick(event);
|
|
3520
|
+
}
|
|
3521
|
+
};
|
|
3522
|
+
const _isOnPath = (isOnPath && isOnPath) || (drilldownItemPath && drilldownItemPath.includes(itemId)) || false;
|
|
3523
|
+
let drill;
|
|
3524
|
+
if (direction) {
|
|
3525
|
+
if (direction === 'down') {
|
|
3526
|
+
drill = (event) => onDrillIn &&
|
|
3527
|
+
onDrillIn(event, menuId, typeof drilldownMenu === 'function'
|
|
3528
|
+
? drilldownMenu().props.id
|
|
3529
|
+
: drilldownMenu.props.id, itemId);
|
|
3530
|
+
}
|
|
3531
|
+
else {
|
|
3532
|
+
drill = (event) => onDrillOut && onDrillOut(event, parentMenu, itemId);
|
|
3533
|
+
}
|
|
3534
|
+
}
|
|
3535
|
+
let additionalProps = {};
|
|
3536
|
+
if (Component === 'a') {
|
|
3537
|
+
additionalProps = {
|
|
3538
|
+
href: to,
|
|
3539
|
+
'aria-disabled': isDisabled || isAriaDisabled ? true : null,
|
|
3540
|
+
// prevent invalid 'disabled' attribute on <a> tags
|
|
3541
|
+
disabled: null,
|
|
3542
|
+
target: isExternalLink ? '_blank' : target,
|
|
3543
|
+
rel,
|
|
3544
|
+
download
|
|
3545
|
+
};
|
|
3546
|
+
}
|
|
3547
|
+
else if (Component === 'button') {
|
|
3548
|
+
additionalProps = {
|
|
3549
|
+
type: 'button',
|
|
3550
|
+
'aria-disabled': isAriaDisabled ? true : null
|
|
3551
|
+
};
|
|
3552
|
+
}
|
|
3553
|
+
if (isOnPath) {
|
|
3554
|
+
additionalProps['aria-expanded'] = true;
|
|
3555
|
+
}
|
|
3556
|
+
else if (hasFlyout) {
|
|
3557
|
+
additionalProps['aria-haspopup'] = 'menu';
|
|
3558
|
+
additionalProps['aria-expanded'] = flyoutVisible;
|
|
3559
|
+
}
|
|
3560
|
+
const getAriaCurrent = () => {
|
|
3561
|
+
if (isActive !== null) {
|
|
3562
|
+
if (isActive) {
|
|
3563
|
+
return 'page';
|
|
3564
|
+
}
|
|
3565
|
+
else {
|
|
3566
|
+
return null;
|
|
3567
|
+
}
|
|
3568
|
+
}
|
|
3569
|
+
else if (itemId !== null && activeItemId !== null) {
|
|
3570
|
+
return itemId === activeItemId;
|
|
3571
|
+
}
|
|
3572
|
+
return null;
|
|
3573
|
+
};
|
|
3574
|
+
const getIsSelected = () => {
|
|
3575
|
+
if (isSelected !== null) {
|
|
3576
|
+
return isSelected;
|
|
3577
|
+
}
|
|
3578
|
+
else if (selected !== null && itemId !== null) {
|
|
3579
|
+
return (Array.isArray(selected) && selected.includes(itemId)) || itemId === selected;
|
|
3580
|
+
}
|
|
3581
|
+
return false;
|
|
3582
|
+
};
|
|
3583
|
+
const onMouseOver = () => {
|
|
3584
|
+
if (disableHover) {
|
|
3585
|
+
return;
|
|
3586
|
+
}
|
|
3587
|
+
if (hasFlyout) {
|
|
3588
|
+
showFlyout(true);
|
|
3589
|
+
}
|
|
3590
|
+
else {
|
|
3591
|
+
setFlyoutRef(null);
|
|
3592
|
+
}
|
|
3593
|
+
};
|
|
3594
|
+
React.useEffect(() => {
|
|
3595
|
+
if (isFocused && ref.current) {
|
|
3596
|
+
const itemEl = ref.current;
|
|
3597
|
+
const parentListEl = itemEl.parentElement;
|
|
3598
|
+
if (parentListEl) {
|
|
3599
|
+
const isAboveTop = itemEl.offsetTop - parentListEl.offsetTop < parentListEl.scrollTop;
|
|
3600
|
+
const isBelowBottom = itemEl.offsetTop - parentListEl.offsetTop + itemEl.clientHeight;
|
|
3601
|
+
if (isAboveTop || isBelowBottom) {
|
|
3602
|
+
itemEl.scrollIntoView({ behavior: 'auto', block: 'nearest' });
|
|
3603
|
+
}
|
|
3604
|
+
}
|
|
3605
|
+
}
|
|
3606
|
+
}, [isFocused]);
|
|
3607
|
+
const isSelectMenu = menuRole === 'listbox';
|
|
3608
|
+
const renderItem = (React.createElement(React.Fragment, null,
|
|
3609
|
+
React.createElement(GenerateId, null, (randomId) => (React.createElement(Component, Object.assign({ id: id, tabIndex: -1, className: css(menuStyles.menuItem, getIsSelected() && !hasCheckbox && menuStyles.modifiers.selected, className), "aria-current": getAriaCurrent() }, (!hasCheckbox && { disabled: isDisabled, 'aria-label': ariaLabel }), (!hasCheckbox && !flyoutMenu && { role: isSelectMenu ? 'option' : 'menuitem' }), (!hasCheckbox && !flyoutMenu && isSelectMenu && { 'aria-selected': getIsSelected() }), { ref: innerRef }, (!hasCheckbox && {
|
|
3610
|
+
onClick: (event) => {
|
|
3611
|
+
if (!isAriaDisabled) {
|
|
3612
|
+
onItemSelect(event, onSelect);
|
|
3613
|
+
drill && drill(event);
|
|
3614
|
+
flyoutMenu && handleFlyout(event);
|
|
3615
|
+
}
|
|
3616
|
+
else {
|
|
3617
|
+
event.preventDefault();
|
|
3618
|
+
}
|
|
3619
|
+
}
|
|
3620
|
+
}), (hasCheckbox && { htmlFor: randomId }), additionalProps),
|
|
3621
|
+
React.createElement("span", { className: css(menuStyles.menuItemMain) },
|
|
3622
|
+
direction === 'up' && (React.createElement("span", { className: css(menuStyles.menuItemToggleIcon) },
|
|
3623
|
+
React.createElement(AngleLeftIcon, { "aria-hidden": true }))),
|
|
3624
|
+
icon && React.createElement("span", { className: css(menuStyles.menuItemIcon) }, icon),
|
|
3625
|
+
hasCheckbox && (React.createElement("span", { className: css(menuStyles.menuItemCheck) },
|
|
3626
|
+
React.createElement(Checkbox, { id: randomId, component: "span", isChecked: isSelected || false, onChange: (event) => onItemSelect(event, onSelect), isDisabled: isDisabled, "aria-disabled": isAriaDisabled }))),
|
|
3627
|
+
React.createElement("span", { className: css(menuStyles.menuItemText) }, children),
|
|
3628
|
+
isExternalLink && (React.createElement("span", { className: css(menuStyles.menuItemExternalIcon) },
|
|
3629
|
+
React.createElement(ExternalLinkAltIcon, { "aria-hidden": true }))),
|
|
3630
|
+
(flyoutMenu || direction === 'down') && (React.createElement("span", { className: css(menuStyles.menuItemToggleIcon) },
|
|
3631
|
+
React.createElement(AngleRightIcon, { "aria-hidden": true }))),
|
|
3632
|
+
getIsSelected() && (React.createElement("span", { className: css(menuStyles.menuItemSelectIcon) },
|
|
3633
|
+
React.createElement(CheckIcon, { "aria-hidden": true })))),
|
|
3634
|
+
description && direction !== 'up' && (React.createElement("span", { className: css(menuStyles.menuItemDescription) },
|
|
3635
|
+
React.createElement("span", null, description)))))),
|
|
3636
|
+
flyoutVisible && (React.createElement(MenuContext.Provider, { value: { disableHover } },
|
|
3637
|
+
React.createElement(FlyoutContext.Provider, { value: { direction: flyoutXDirection } }, flyoutMenu))),
|
|
3638
|
+
typeof drilldownMenu === 'function' ? drilldownMenu() : drilldownMenu,
|
|
3639
|
+
React.createElement(MenuItemContext.Provider, { value: { itemId, isDisabled } },
|
|
3640
|
+
actions,
|
|
3641
|
+
isFavorited !== null && (React.createElement(MenuItemAction, { icon: "favorites", isFavorited: isFavorited, "aria-label": isFavorited ? 'starred' : 'not starred', onClick: (event) => onActionClick(event, itemId), tabIndex: -1, actionId: "fav" })))));
|
|
3642
|
+
return (React.createElement("li", Object.assign({ className: css(menuStyles.menuListItem, isDisabled && menuStyles.modifiers.disabled, isAriaDisabled && menuStyles.modifiers.ariaDisabled, _isOnPath && menuStyles.modifiers.currentPath, isLoadButton && menuStyles.modifiers.load, isLoading && menuStyles.modifiers.loading, isFocused && 'pf-m-focus', isDanger && menuStyles.modifiers.danger, className), onMouseOver: () => {
|
|
3643
|
+
if (!isAriaDisabled) {
|
|
3644
|
+
onMouseOver();
|
|
3645
|
+
}
|
|
3646
|
+
} }, (flyoutMenu && !isAriaDisabled && { onKeyDown: handleFlyout }), { ref: ref, role: !hasCheckbox ? 'none' : 'menuitem' }, (hasCheckbox && { 'aria-label': ariaLabel }), props), tooltipProps ? React.createElement(Tooltip, Object.assign({}, tooltipProps), renderItem) : renderItem));
|
|
3647
|
+
};
|
|
3648
|
+
const MenuItem = React.forwardRef((props, ref) => (React.createElement(MenuItemBase, Object.assign({}, props, { innerRef: ref }))));
|
|
3649
|
+
MenuItem.displayName = 'MenuItem';
|
|
3650
|
+
|
|
3651
|
+
const MenuList = (_a) => {
|
|
3652
|
+
var { children = null, className, isAriaMultiselectable = false, 'aria-label': ariaLabel } = _a, props = __rest(_a, ["children", "className", "isAriaMultiselectable", 'aria-label']);
|
|
3653
|
+
const { role } = React.useContext(MenuContext);
|
|
3654
|
+
return (React.createElement("ul", Object.assign({ role: role }, (role === 'listbox' && { 'aria-multiselectable': isAriaMultiselectable }), { className: css(menuStyles.menuList, className), "aria-label": ariaLabel }, props), children));
|
|
3655
|
+
};
|
|
3656
|
+
MenuList.displayName = 'MenuList';
|
|
3657
|
+
|
|
3658
|
+
const styles = {
|
|
3659
|
+
"menuToggle": "pf-v6-c-menu-toggle",
|
|
3660
|
+
"menuToggleButton": "pf-v6-c-menu-toggle__button",
|
|
3661
|
+
"menuToggleControls": "pf-v6-c-menu-toggle__controls",
|
|
3662
|
+
"menuToggleCount": "pf-v6-c-menu-toggle__count",
|
|
3663
|
+
"menuToggleIcon": "pf-v6-c-menu-toggle__icon",
|
|
3664
|
+
"menuToggleStatusIcon": "pf-v6-c-menu-toggle__status-icon",
|
|
3665
|
+
"menuToggleText": "pf-v6-c-menu-toggle__text",
|
|
3666
|
+
"menuToggleToggleIcon": "pf-v6-c-menu-toggle__toggle-icon",
|
|
3667
|
+
"modifiers": {
|
|
3668
|
+
"primary": "pf-m-primary",
|
|
3669
|
+
"secondary": "pf-m-secondary",
|
|
3670
|
+
"fullHeight": "pf-m-full-height",
|
|
3671
|
+
"fullWidth": "pf-m-full-width",
|
|
3672
|
+
"plain": "pf-m-plain",
|
|
3673
|
+
"expanded": "pf-m-expanded",
|
|
3674
|
+
"disabled": "pf-m-disabled",
|
|
3675
|
+
"small": "pf-m-small",
|
|
3676
|
+
"success": "pf-m-success",
|
|
3677
|
+
"warning": "pf-m-warning",
|
|
3678
|
+
"danger": "pf-m-danger",
|
|
3679
|
+
"placeholder": "pf-m-placeholder",
|
|
3680
|
+
"splitButton": "pf-m-split-button",
|
|
3681
|
+
"standalone": "pf-m-standalone",
|
|
3682
|
+
"typeahead": "pf-m-typeahead",
|
|
3683
|
+
"text": "pf-m-text",
|
|
3684
|
+
"avatar": "pf-m-avatar"
|
|
3685
|
+
}};
|
|
3686
|
+
|
|
3687
|
+
const CaretDownIconConfig = {
|
|
3688
|
+
name: 'CaretDownIcon',
|
|
3689
|
+
height: 512,
|
|
3690
|
+
width: 320,
|
|
3691
|
+
svgPath: 'M31.3 192h257.3c17.8 0 26.7 21.5 14.1 34.1L174.1 354.8c-7.8 7.8-20.5 7.8-28.3 0L17.2 226.1C4.6 213.5 13.5 192 31.3 192z',
|
|
3692
|
+
yOffset: 0,
|
|
3693
|
+
xOffset: 0,
|
|
3694
|
+
};
|
|
3695
|
+
|
|
3696
|
+
const CaretDownIcon = createIcon(CaretDownIconConfig);
|
|
3697
|
+
|
|
3698
|
+
var MenuToggleStatus;
|
|
3699
|
+
(function (MenuToggleStatus) {
|
|
3700
|
+
MenuToggleStatus["success"] = "success";
|
|
3701
|
+
MenuToggleStatus["danger"] = "danger";
|
|
3702
|
+
MenuToggleStatus["warning"] = "warning";
|
|
3703
|
+
})(MenuToggleStatus || (MenuToggleStatus = {}));
|
|
3704
|
+
var MenuToggleSize;
|
|
3705
|
+
(function (MenuToggleSize) {
|
|
3706
|
+
MenuToggleSize["default"] = "default";
|
|
3707
|
+
MenuToggleSize["sm"] = "sm";
|
|
3708
|
+
})(MenuToggleSize || (MenuToggleSize = {}));
|
|
3709
|
+
class MenuToggleBase extends React.Component {
|
|
3710
|
+
constructor() {
|
|
3711
|
+
super(...arguments);
|
|
3712
|
+
this.displayName = 'MenuToggleBase';
|
|
3713
|
+
this.state = {
|
|
3714
|
+
ouiaStateId: getDefaultOUIAId(MenuToggle.displayName, this.props.variant)
|
|
3715
|
+
};
|
|
3716
|
+
}
|
|
3717
|
+
render() {
|
|
3718
|
+
const _a = this.props, { children, className, icon, badge, isExpanded, isDisabled, isFullHeight, isFullWidth, isPlaceholder, splitButtonItems, variant, status, statusIcon, innerRef, onClick, 'aria-label': ariaLabel, ouiaId, ouiaSafe, size } = _a, otherProps = __rest(_a, ["children", "className", "icon", "badge", "isExpanded", "isDisabled", "isFullHeight", "isFullWidth", "isPlaceholder", "splitButtonItems", "variant", "status", "statusIcon", "innerRef", "onClick", 'aria-label', "ouiaId", "ouiaSafe", "size"]);
|
|
3719
|
+
const isPlain = variant === 'plain';
|
|
3720
|
+
const isPlainText = variant === 'plainText';
|
|
3721
|
+
const isTypeahead = variant === 'typeahead';
|
|
3722
|
+
const ouiaProps = getOUIAProps(MenuToggle.displayName, ouiaId !== null && ouiaId !== void 0 ? ouiaId : this.state.ouiaStateId, ouiaSafe);
|
|
3723
|
+
let _statusIcon = statusIcon;
|
|
3724
|
+
if (!statusIcon) {
|
|
3725
|
+
switch (status) {
|
|
3726
|
+
case MenuToggleStatus.success:
|
|
3727
|
+
_statusIcon = React.createElement(CheckCircleIcon, { "aria-hidden": "true" });
|
|
3728
|
+
break;
|
|
3729
|
+
case MenuToggleStatus.warning:
|
|
3730
|
+
_statusIcon = React.createElement(ExclamationTriangleIcon, { "aria-hidden": "true" });
|
|
3731
|
+
break;
|
|
3732
|
+
case MenuToggleStatus.danger:
|
|
3733
|
+
_statusIcon = React.createElement(ExclamationCircleIcon, { "aria-hidden": "true" });
|
|
3734
|
+
break;
|
|
3735
|
+
}
|
|
3736
|
+
}
|
|
3737
|
+
const toggleControls = (React.createElement("span", { className: css(styles.menuToggleControls) },
|
|
3738
|
+
status !== undefined && React.createElement("span", { className: css(styles.menuToggleStatusIcon) }, _statusIcon),
|
|
3739
|
+
React.createElement("span", { className: css(styles.menuToggleToggleIcon) },
|
|
3740
|
+
React.createElement(CaretDownIcon, { "aria-hidden": true }))));
|
|
3741
|
+
const content = (React.createElement(React.Fragment, null,
|
|
3742
|
+
icon && React.createElement("span", { className: css(styles.menuToggleIcon) }, icon),
|
|
3743
|
+
isTypeahead ? children : children && React.createElement("span", { className: css(styles.menuToggleText) }, children),
|
|
3744
|
+
React.isValidElement(badge) && React.createElement("span", { className: css(styles.menuToggleCount) }, badge),
|
|
3745
|
+
isTypeahead ? (React.createElement("button", Object.assign({ type: "button", className: css(styles.menuToggleButton), "aria-expanded": isExpanded, onClick: onClick, "aria-label": ariaLabel || 'Menu toggle', tabIndex: -1 }, ouiaProps), toggleControls)) : (!isPlain && toggleControls)));
|
|
3746
|
+
const commonStyles = css(styles.menuToggle, isExpanded && styles.modifiers.expanded, variant === 'primary' && styles.modifiers.primary, variant === 'secondary' && styles.modifiers.secondary, status && styles.modifiers[status], (isPlain || isPlainText) && styles.modifiers.plain, isPlainText && 'pf-m-text', isFullHeight && styles.modifiers.fullHeight, isFullWidth && styles.modifiers.fullWidth, isDisabled && styles.modifiers.disabled, isPlaceholder && styles.modifiers.placeholder, size === MenuToggleSize.sm && styles.modifiers.small, className);
|
|
3747
|
+
const componentProps = Object.assign(Object.assign({ children: content }, (isDisabled && { disabled: true })), otherProps);
|
|
3748
|
+
if (isTypeahead) {
|
|
3749
|
+
return (React.createElement("div", Object.assign({ ref: innerRef, className: css(commonStyles, styles.modifiers.typeahead) }, componentProps)));
|
|
3750
|
+
}
|
|
3751
|
+
if (splitButtonItems) {
|
|
3752
|
+
return (React.createElement("div", { ref: innerRef, className: css(commonStyles, styles.modifiers.splitButton) },
|
|
3753
|
+
splitButtonItems,
|
|
3754
|
+
React.createElement("button", Object.assign({ className: css(styles.menuToggleButton, children && styles.modifiers.text), type: "button", "aria-expanded": isExpanded, "aria-label": ariaLabel, disabled: isDisabled, onClick: onClick }, otherProps, ouiaProps),
|
|
3755
|
+
children && React.createElement("span", { className: css(styles.menuToggleText) }, children),
|
|
3756
|
+
toggleControls)));
|
|
3757
|
+
}
|
|
3758
|
+
return (React.createElement("button", Object.assign({ className: css(commonStyles), type: "button", "aria-label": ariaLabel, "aria-expanded": isExpanded, ref: innerRef, disabled: isDisabled, onClick: onClick }, componentProps, ouiaProps)));
|
|
3759
|
+
}
|
|
3760
|
+
}
|
|
3761
|
+
MenuToggleBase.defaultProps = {
|
|
3762
|
+
className: '',
|
|
3763
|
+
isExpanded: false,
|
|
3764
|
+
isDisabled: false,
|
|
3765
|
+
isFullWidth: false,
|
|
3766
|
+
isFullHeight: false,
|
|
3767
|
+
isPlaceholder: false,
|
|
3768
|
+
size: 'default',
|
|
3769
|
+
ouiaSafe: true
|
|
3770
|
+
};
|
|
3771
|
+
const MenuToggle = React.forwardRef((props, ref) => (React.createElement(MenuToggleBase, Object.assign({ innerRef: ref }, props))));
|
|
3772
|
+
MenuToggle.displayName = 'MenuToggle';
|
|
3773
|
+
|
|
3774
|
+
const dividerStyles = {
|
|
3775
|
+
"divider": "pf-v6-c-divider",
|
|
3776
|
+
"modifiers": {
|
|
3777
|
+
"hidden": "pf-m-hidden",
|
|
3778
|
+
"hiddenOnSm": "pf-m-hidden-on-sm",
|
|
3779
|
+
"visibleOnSm": "pf-m-visible-on-sm",
|
|
3780
|
+
"hiddenOnMd": "pf-m-hidden-on-md",
|
|
3781
|
+
"visibleOnMd": "pf-m-visible-on-md",
|
|
3782
|
+
"hiddenOnLg": "pf-m-hidden-on-lg",
|
|
3783
|
+
"visibleOnLg": "pf-m-visible-on-lg",
|
|
3784
|
+
"hiddenOnXl": "pf-m-hidden-on-xl",
|
|
3785
|
+
"visibleOnXl": "pf-m-visible-on-xl",
|
|
3786
|
+
"hiddenOn_2xl": "pf-m-hidden-on-2xl",
|
|
3787
|
+
"visibleOn_2xl": "pf-m-visible-on-2xl",
|
|
3788
|
+
"horizontal": "pf-m-horizontal",
|
|
3789
|
+
"vertical": "pf-m-vertical",
|
|
3790
|
+
"insetNone": "pf-m-inset-none",
|
|
3791
|
+
"insetXs": "pf-m-inset-xs",
|
|
3792
|
+
"insetSm": "pf-m-inset-sm",
|
|
3793
|
+
"insetMd": "pf-m-inset-md",
|
|
3794
|
+
"insetLg": "pf-m-inset-lg",
|
|
3795
|
+
"insetXl": "pf-m-inset-xl",
|
|
3796
|
+
"inset_2xl": "pf-m-inset-2xl",
|
|
3797
|
+
"inset_3xl": "pf-m-inset-3xl",
|
|
3798
|
+
"horizontalOnSm": "pf-m-horizontal-on-sm",
|
|
3799
|
+
"verticalOnSm": "pf-m-vertical-on-sm",
|
|
3800
|
+
"insetNoneOnSm": "pf-m-inset-none-on-sm",
|
|
3801
|
+
"insetXsOnSm": "pf-m-inset-xs-on-sm",
|
|
3802
|
+
"insetSmOnSm": "pf-m-inset-sm-on-sm",
|
|
3803
|
+
"insetMdOnSm": "pf-m-inset-md-on-sm",
|
|
3804
|
+
"insetLgOnSm": "pf-m-inset-lg-on-sm",
|
|
3805
|
+
"insetXlOnSm": "pf-m-inset-xl-on-sm",
|
|
3806
|
+
"inset_2xlOnSm": "pf-m-inset-2xl-on-sm",
|
|
3807
|
+
"inset_3xlOnSm": "pf-m-inset-3xl-on-sm",
|
|
3808
|
+
"horizontalOnMd": "pf-m-horizontal-on-md",
|
|
3809
|
+
"verticalOnMd": "pf-m-vertical-on-md",
|
|
3810
|
+
"insetNoneOnMd": "pf-m-inset-none-on-md",
|
|
3811
|
+
"insetXsOnMd": "pf-m-inset-xs-on-md",
|
|
3812
|
+
"insetSmOnMd": "pf-m-inset-sm-on-md",
|
|
3813
|
+
"insetMdOnMd": "pf-m-inset-md-on-md",
|
|
3814
|
+
"insetLgOnMd": "pf-m-inset-lg-on-md",
|
|
3815
|
+
"insetXlOnMd": "pf-m-inset-xl-on-md",
|
|
3816
|
+
"inset_2xlOnMd": "pf-m-inset-2xl-on-md",
|
|
3817
|
+
"inset_3xlOnMd": "pf-m-inset-3xl-on-md",
|
|
3818
|
+
"horizontalOnLg": "pf-m-horizontal-on-lg",
|
|
3819
|
+
"verticalOnLg": "pf-m-vertical-on-lg",
|
|
3820
|
+
"insetNoneOnLg": "pf-m-inset-none-on-lg",
|
|
3821
|
+
"insetXsOnLg": "pf-m-inset-xs-on-lg",
|
|
3822
|
+
"insetSmOnLg": "pf-m-inset-sm-on-lg",
|
|
3823
|
+
"insetMdOnLg": "pf-m-inset-md-on-lg",
|
|
3824
|
+
"insetLgOnLg": "pf-m-inset-lg-on-lg",
|
|
3825
|
+
"insetXlOnLg": "pf-m-inset-xl-on-lg",
|
|
3826
|
+
"inset_2xlOnLg": "pf-m-inset-2xl-on-lg",
|
|
3827
|
+
"inset_3xlOnLg": "pf-m-inset-3xl-on-lg",
|
|
3828
|
+
"horizontalOnXl": "pf-m-horizontal-on-xl",
|
|
3829
|
+
"verticalOnXl": "pf-m-vertical-on-xl",
|
|
3830
|
+
"insetNoneOnXl": "pf-m-inset-none-on-xl",
|
|
3831
|
+
"insetXsOnXl": "pf-m-inset-xs-on-xl",
|
|
3832
|
+
"insetSmOnXl": "pf-m-inset-sm-on-xl",
|
|
3833
|
+
"insetMdOnXl": "pf-m-inset-md-on-xl",
|
|
3834
|
+
"insetLgOnXl": "pf-m-inset-lg-on-xl",
|
|
3835
|
+
"insetXlOnXl": "pf-m-inset-xl-on-xl",
|
|
3836
|
+
"inset_2xlOnXl": "pf-m-inset-2xl-on-xl",
|
|
3837
|
+
"inset_3xlOnXl": "pf-m-inset-3xl-on-xl",
|
|
3838
|
+
"horizontalOn_2xl": "pf-m-horizontal-on-2xl",
|
|
3839
|
+
"verticalOn_2xl": "pf-m-vertical-on-2xl",
|
|
3840
|
+
"insetNoneOn_2xl": "pf-m-inset-none-on-2xl",
|
|
3841
|
+
"insetXsOn_2xl": "pf-m-inset-xs-on-2xl",
|
|
3842
|
+
"insetSmOn_2xl": "pf-m-inset-sm-on-2xl",
|
|
3843
|
+
"insetMdOn_2xl": "pf-m-inset-md-on-2xl",
|
|
3844
|
+
"insetLgOn_2xl": "pf-m-inset-lg-on-2xl",
|
|
3845
|
+
"insetXlOn_2xl": "pf-m-inset-xl-on-2xl",
|
|
3846
|
+
"inset_2xlOn_2xl": "pf-m-inset-2xl-on-2xl",
|
|
3847
|
+
"inset_3xlOn_2xl": "pf-m-inset-3xl-on-2xl"
|
|
3848
|
+
}
|
|
3849
|
+
};
|
|
3850
|
+
|
|
3851
|
+
var DividerVariant;
|
|
3852
|
+
(function (DividerVariant) {
|
|
3853
|
+
DividerVariant["hr"] = "hr";
|
|
3854
|
+
DividerVariant["li"] = "li";
|
|
3855
|
+
DividerVariant["div"] = "div";
|
|
3856
|
+
})(DividerVariant || (DividerVariant = {}));
|
|
3857
|
+
const Divider = (_a) => {
|
|
3858
|
+
var { className, component = DividerVariant.hr, inset, orientation } = _a, props = __rest(_a, ["className", "component", "inset", "orientation"]);
|
|
3859
|
+
const Component = component;
|
|
3860
|
+
return (React.createElement(Component, Object.assign({ className: css(dividerStyles.divider, formatBreakpointMods(inset, dividerStyles), formatBreakpointMods(orientation, dividerStyles), className) }, (component !== 'hr' && { role: 'separator' }), props)));
|
|
3861
|
+
};
|
|
3862
|
+
Divider.displayName = 'Divider';
|
|
3863
|
+
|
|
3864
|
+
const DropdownBase = (_a) => {
|
|
3865
|
+
var { children, className, onSelect, isOpen, toggle, shouldFocusToggleOnSelect = false, onOpenChange, onToggleKeydown, isPlain, isScrollable, innerRef, ouiaId, ouiaSafe = true, zIndex = 9999, popperProps, onOpenChangeKeys = ['Escape', 'Tab'], menuHeight, maxMenuHeight, shouldFocusFirstItemOnOpen = false, shouldPreventScrollOnItemFocus = true, focusTimeoutDelay = 0 } = _a, props = __rest(_a, ["children", "className", "onSelect", "isOpen", "toggle", "shouldFocusToggleOnSelect", "onOpenChange", "onToggleKeydown", "isPlain", "isScrollable", "innerRef", "ouiaId", "ouiaSafe", "zIndex", "popperProps", "onOpenChangeKeys", "menuHeight", "maxMenuHeight", "shouldFocusFirstItemOnOpen", "shouldPreventScrollOnItemFocus", "focusTimeoutDelay"]);
|
|
3866
|
+
const localMenuRef = React__default.useRef();
|
|
3867
|
+
const localToggleRef = React__default.useRef();
|
|
3868
|
+
const ouiaProps = useOUIAProps(Dropdown.displayName, ouiaId, ouiaSafe);
|
|
3869
|
+
const menuRef = innerRef || localMenuRef;
|
|
3870
|
+
const toggleRef = typeof toggle === 'function' || (typeof toggle !== 'function' && !toggle.toggleRef)
|
|
3871
|
+
? localToggleRef
|
|
3872
|
+
: toggle === null || toggle === void 0 ? void 0 : toggle.toggleRef;
|
|
3873
|
+
const prevIsOpen = React__default.useRef(isOpen);
|
|
3874
|
+
React__default.useEffect(() => {
|
|
3875
|
+
// menu was opened, focus on first menu item
|
|
3876
|
+
if (prevIsOpen.current === false && isOpen === true && shouldFocusFirstItemOnOpen) {
|
|
3877
|
+
setTimeout(() => {
|
|
3878
|
+
var _a;
|
|
3879
|
+
const firstElement = (_a = menuRef === null || menuRef === void 0 ? void 0 : menuRef.current) === null || _a === void 0 ? void 0 : _a.querySelector('li button:not(:disabled),li input:not(:disabled),li a:not([aria-disabled="true"])');
|
|
3880
|
+
firstElement && firstElement.focus({ preventScroll: shouldPreventScrollOnItemFocus });
|
|
3881
|
+
}, focusTimeoutDelay);
|
|
3882
|
+
}
|
|
3883
|
+
prevIsOpen.current = isOpen;
|
|
3884
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
3885
|
+
}, [isOpen]);
|
|
3886
|
+
React__default.useEffect(() => {
|
|
3887
|
+
const handleMenuKeys = (event) => {
|
|
3888
|
+
var _a, _b, _c, _d;
|
|
3889
|
+
// Close the menu on tab or escape if onOpenChange is provided
|
|
3890
|
+
if (isOpen &&
|
|
3891
|
+
onOpenChange &&
|
|
3892
|
+
(((_a = menuRef.current) === null || _a === void 0 ? void 0 : _a.contains(event.target)) || ((_b = toggleRef.current) === null || _b === void 0 ? void 0 : _b.contains(event.target)))) {
|
|
3893
|
+
if (onOpenChangeKeys.includes(event.key)) {
|
|
3894
|
+
onOpenChange(false);
|
|
3895
|
+
(_c = toggleRef.current) === null || _c === void 0 ? void 0 : _c.focus();
|
|
3896
|
+
}
|
|
3897
|
+
}
|
|
3898
|
+
if ((_d = toggleRef.current) === null || _d === void 0 ? void 0 : _d.contains(event.target)) {
|
|
3899
|
+
if (onToggleKeydown) {
|
|
3900
|
+
onToggleKeydown(event);
|
|
3901
|
+
}
|
|
3902
|
+
else if (isOpen) {
|
|
3903
|
+
onToggleArrowKeydownDefault(event, menuRef);
|
|
3904
|
+
}
|
|
3905
|
+
}
|
|
3906
|
+
};
|
|
3907
|
+
const handleClick = (event) => {
|
|
3908
|
+
var _a, _b;
|
|
3909
|
+
// If the event is not on the toggle and onOpenChange callback is provided, close the menu
|
|
3910
|
+
if (isOpen && onOpenChange && !((_a = toggleRef === null || toggleRef === void 0 ? void 0 : toggleRef.current) === null || _a === void 0 ? void 0 : _a.contains(event.target))) {
|
|
3911
|
+
if (isOpen && !((_b = menuRef.current) === null || _b === void 0 ? void 0 : _b.contains(event.target))) {
|
|
3912
|
+
onOpenChange(false);
|
|
3913
|
+
}
|
|
3914
|
+
}
|
|
3915
|
+
};
|
|
3916
|
+
window.addEventListener('keydown', handleMenuKeys);
|
|
3917
|
+
window.addEventListener('click', handleClick);
|
|
3918
|
+
return () => {
|
|
3919
|
+
window.removeEventListener('keydown', handleMenuKeys);
|
|
3920
|
+
window.removeEventListener('click', handleClick);
|
|
3921
|
+
};
|
|
3922
|
+
}, [
|
|
3923
|
+
isOpen,
|
|
3924
|
+
menuRef,
|
|
3925
|
+
toggleRef,
|
|
3926
|
+
onOpenChange,
|
|
3927
|
+
onOpenChangeKeys,
|
|
3928
|
+
onToggleKeydown,
|
|
3929
|
+
shouldPreventScrollOnItemFocus,
|
|
3930
|
+
shouldFocusFirstItemOnOpen,
|
|
3931
|
+
focusTimeoutDelay
|
|
3932
|
+
]);
|
|
3933
|
+
const scrollable = maxMenuHeight !== undefined || menuHeight !== undefined || isScrollable;
|
|
3934
|
+
const menu = (React__default.createElement(Menu, Object.assign({ className: css(className), ref: menuRef, onSelect: (event, value) => {
|
|
3935
|
+
var _a;
|
|
3936
|
+
onSelect && onSelect(event, value);
|
|
3937
|
+
shouldFocusToggleOnSelect && ((_a = toggleRef.current) === null || _a === void 0 ? void 0 : _a.focus());
|
|
3938
|
+
}, isPlain: isPlain, isScrollable: scrollable }, props, ouiaProps),
|
|
3939
|
+
React__default.createElement(MenuContent, { menuHeight: menuHeight, maxMenuHeight: maxMenuHeight }, children)));
|
|
3940
|
+
return (React__default.createElement(Popper, Object.assign({ trigger: typeof toggle === 'function' ? toggle(toggleRef) : toggle.toggleNode, triggerRef: toggleRef, popper: menu, popperRef: menuRef, isVisible: isOpen, zIndex: zIndex }, popperProps)));
|
|
3941
|
+
};
|
|
3942
|
+
const Dropdown = React__default.forwardRef((props, ref) => (React__default.createElement(DropdownBase, Object.assign({ innerRef: ref }, props))));
|
|
3943
|
+
Dropdown.displayName = 'Dropdown';
|
|
3944
|
+
|
|
3945
|
+
const DropdownItemBase = (_a) => {
|
|
3946
|
+
var { children, className, description, isDisabled, isAriaDisabled, value, onClick, ouiaId, ouiaSafe, innerRef, tooltipProps } = _a, props = __rest(_a, ["children", "className", "description", "isDisabled", "isAriaDisabled", "value", "onClick", "ouiaId", "ouiaSafe", "innerRef", "tooltipProps"]);
|
|
3947
|
+
const ouiaProps = useOUIAProps(DropdownItem.displayName, ouiaId, ouiaSafe);
|
|
3948
|
+
return (React__default.createElement(MenuItem, Object.assign({ className: css(className), description: description, isDisabled: isDisabled, isAriaDisabled: isAriaDisabled, itemId: value, onClick: onClick, tooltipProps: tooltipProps, ref: innerRef }, ouiaProps, props), children));
|
|
3949
|
+
};
|
|
3950
|
+
const DropdownItem = React__default.forwardRef((props, ref) => (React__default.createElement(DropdownItemBase, Object.assign({}, props, { innerRef: ref }))));
|
|
3951
|
+
DropdownItem.displayName = 'DropdownItem';
|
|
3952
|
+
|
|
3953
|
+
const DropdownList = (_a) => {
|
|
3954
|
+
var { children, className } = _a, props = __rest(_a, ["children", "className"]);
|
|
3955
|
+
return (React__default.createElement(MenuList, Object.assign({ className: css(className) }, props), children));
|
|
3956
|
+
};
|
|
3957
|
+
DropdownList.displayName = 'DropdownList';
|
|
3958
|
+
|
|
3959
|
+
const AngleDownIconConfig = {
|
|
3960
|
+
name: 'AngleDownIcon',
|
|
3961
|
+
height: 512,
|
|
3962
|
+
width: 320,
|
|
3963
|
+
svgPath: 'M143 352.3L7 216.3c-9.4-9.4-9.4-24.6 0-33.9l22.6-22.6c9.4-9.4 24.6-9.4 33.9 0l96.4 96.4 96.4-96.4c9.4-9.4 24.6-9.4 33.9 0l22.6 22.6c9.4 9.4 9.4 24.6 0 33.9l-136 136c-9.2 9.4-24.4 9.4-33.8 0z',
|
|
3964
|
+
yOffset: 0,
|
|
3965
|
+
xOffset: 0,
|
|
3966
|
+
};
|
|
3967
|
+
|
|
3968
|
+
const AngleDownIcon = createIcon(AngleDownIconConfig);
|
|
3969
|
+
|
|
3970
|
+
export { ASTERISK as A, Button as B, CheckCircleIcon as C, Divider as D, ExclamationTriangleIcon as E, getUniqueId as F, GenerateId as G, useIsomorphicLayoutEffect as H, Tooltip as I, BellIcon as J, KeyTypes as K, InfoCircleIcon as L, MenuToggle as M, checkStyles as N, StarIcon as O, Popper as P, Checkbox as Q, setTabIndex as R, Spinner as S, TimesIcon as T, handleArrows as U, ValidatedOptions as V, canUseDOM as a, createIcon as b, css as c, ExclamationCircleIcon as d, getOUIAProps as e, statusIcons as f, getDefaultOUIAId as g, ButtonVariant as h, CaretDownIcon as i, Badge as j, AngleDownIcon as k, getVerticalBreakpoint as l, menuStyles as m, getBreakpoint as n, formatBreakpointMods as o, t_global_breakpoint_2xl as p, t_global_breakpoint_xl as q, t_global_breakpoint_lg as r, setBreakpointCssVars as s, trimLeft as t, useOUIAProps as u, t_global_breakpoint_md as v, toCamel as w, Dropdown as x, DropdownList as y, DropdownItem as z };
|