@deque/cauldron-react 5.8.1 → 5.9.0-canary.07ef06bd
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/LICENSE +362 -0
- package/README.md +20 -10
- package/lib/components/Alert/index.d.ts +4 -2
- package/lib/components/Combobox/Combobox.d.ts +30 -0
- package/lib/components/Combobox/ComboboxContext.d.ts +22 -0
- package/lib/components/Combobox/ComboboxGroup.d.ts +7 -0
- package/lib/components/Combobox/ComboboxOption.d.ts +12 -0
- package/lib/components/Combobox/index.d.ts +3 -0
- package/lib/components/Dialog/index.d.ts +9 -2
- package/lib/components/Listbox/Listbox.d.ts +16 -0
- package/lib/components/Listbox/ListboxContext.d.ts +27 -0
- package/lib/components/Listbox/ListboxGroup.d.ts +9 -0
- package/lib/components/Listbox/ListboxOption.d.ts +10 -0
- package/lib/components/Listbox/index.d.ts +4 -0
- package/lib/components/Modal/index.d.ts +4 -2
- package/lib/components/Popover/index.d.ts +31 -0
- package/lib/components/TagButton/index.d.ts +11 -0
- package/lib/index.d.ts +4 -0
- package/lib/index.js +781 -9
- package/lib/utils/useIntersectionRef.d.ts +12 -0
- package/package.json +4 -3
package/lib/index.js
CHANGED
|
@@ -961,7 +961,7 @@ var ClickOutsideListener = /** @class */ (function (_super) {
|
|
|
961
961
|
return ClickOutsideListener;
|
|
962
962
|
}(React__default["default"].Component));
|
|
963
963
|
|
|
964
|
-
var _a$
|
|
964
|
+
var _a$2 = tslib.__read([38, 40, 9, 13, 32, 27], 6), up = _a$2[0], down$1 = _a$2[1], tab = _a$2[2], enter = _a$2[3], space = _a$2[4], esc = _a$2[5];
|
|
965
965
|
var OptionsMenuList = /** @class */ (function (_super) {
|
|
966
966
|
tslib.__extends(OptionsMenuList, _super);
|
|
967
967
|
function OptionsMenuList(props) {
|
|
@@ -1096,7 +1096,7 @@ var OptionsMenuList = /** @class */ (function (_super) {
|
|
|
1096
1096
|
return OptionsMenuList;
|
|
1097
1097
|
}(React__default["default"].Component));
|
|
1098
1098
|
|
|
1099
|
-
var _a = tslib.__read([40], 1), down = _a[0];
|
|
1099
|
+
var _a$1 = tslib.__read([40], 1), down = _a$1[0];
|
|
1100
1100
|
var OptionsMenu = /** @class */ (function (_super) {
|
|
1101
1101
|
tslib.__extends(OptionsMenu, _super);
|
|
1102
1102
|
function OptionsMenu(props) {
|
|
@@ -1664,22 +1664,32 @@ var Dialog = /** @class */ (function (_super) {
|
|
|
1664
1664
|
return Dialog;
|
|
1665
1665
|
}(React__default["default"].Component));
|
|
1666
1666
|
var DialogContent = function (_a) {
|
|
1667
|
-
var children = _a.children, className = _a.className, other = tslib.__rest(_a, ["children", "className"]);
|
|
1668
|
-
return (React__default["default"].createElement("div", tslib.__assign({ className: classNames__default["default"]('Dialog__content', className
|
|
1667
|
+
var children = _a.children, className = _a.className, align = _a.align, other = tslib.__rest(_a, ["children", "className", "align"]);
|
|
1668
|
+
return (React__default["default"].createElement("div", tslib.__assign({ className: classNames__default["default"]('Dialog__content', className, {
|
|
1669
|
+
'text--align-left': align === 'left',
|
|
1670
|
+
'text--align-center': align === 'center',
|
|
1671
|
+
'text--align-right': align === 'right'
|
|
1672
|
+
}) }, other), children));
|
|
1669
1673
|
};
|
|
1670
1674
|
DialogContent.displayName = 'DialogContent';
|
|
1671
1675
|
DialogContent.propTypes = {
|
|
1672
1676
|
className: PropTypes__default["default"].string,
|
|
1673
|
-
children: PropTypes__default["default"].node
|
|
1677
|
+
children: PropTypes__default["default"].node,
|
|
1678
|
+
align: PropTypes__default["default"].string
|
|
1674
1679
|
};
|
|
1675
1680
|
var DialogFooter = function (_a) {
|
|
1676
|
-
var children = _a.children, className = _a.className, other = tslib.__rest(_a, ["children", "className"]);
|
|
1677
|
-
return (React__default["default"].createElement("div", tslib.__assign({ className: classNames__default["default"]('Dialog__footer', className
|
|
1681
|
+
var children = _a.children, className = _a.className, align = _a.align, other = tslib.__rest(_a, ["children", "className", "align"]);
|
|
1682
|
+
return (React__default["default"].createElement("div", tslib.__assign({ className: classNames__default["default"]('Dialog__footer', className, {
|
|
1683
|
+
'text--align-left': align === 'left',
|
|
1684
|
+
'text--align-center': align === 'center',
|
|
1685
|
+
'text--align-right': align === 'right'
|
|
1686
|
+
}) }, other), children));
|
|
1678
1687
|
};
|
|
1679
1688
|
DialogFooter.displayName = 'DialogFooter';
|
|
1680
1689
|
DialogFooter.propTypes = {
|
|
1681
1690
|
className: PropTypes__default["default"].string,
|
|
1682
|
-
children: PropTypes__default["default"].node
|
|
1691
|
+
children: PropTypes__default["default"].node,
|
|
1692
|
+
align: PropTypes__default["default"].string
|
|
1683
1693
|
};
|
|
1684
1694
|
|
|
1685
1695
|
var Alert = function (_a) {
|
|
@@ -1813,7 +1823,10 @@ function Tooltip(_a) {
|
|
|
1813
1823
|
placement: initialPlacement,
|
|
1814
1824
|
modifiers: [
|
|
1815
1825
|
{ name: 'preventOverflow', options: { padding: 8 } },
|
|
1816
|
-
{
|
|
1826
|
+
{
|
|
1827
|
+
name: 'flip',
|
|
1828
|
+
options: { fallbackPlacements: ['left', 'right', 'top', 'bottom'] }
|
|
1829
|
+
},
|
|
1817
1830
|
{ name: 'offset', options: { offset: [0, 8] } },
|
|
1818
1831
|
{ name: 'arrow', options: { padding: 5, element: arrowElement } }
|
|
1819
1832
|
]
|
|
@@ -3157,6 +3170,15 @@ Tag.propTypes = {
|
|
|
3157
3170
|
className: PropTypes__default["default"].string
|
|
3158
3171
|
};
|
|
3159
3172
|
|
|
3173
|
+
var TagButton = React__default["default"].forwardRef(function (_a, ref) {
|
|
3174
|
+
var label = _a.label, value = _a.value, icon = _a.icon, className = _a.className, rest = tslib.__rest(_a, ["label", "value", "icon", "className"]);
|
|
3175
|
+
return (React__default["default"].createElement(Button, tslib.__assign({ variant: "tag", className: classNames__default["default"]('TagButton', className), ref: ref }, rest),
|
|
3176
|
+
React__default["default"].createElement(TagLabel, null, label),
|
|
3177
|
+
value,
|
|
3178
|
+
React__default["default"].createElement(Icon, { className: "TagButton__icon", type: icon })));
|
|
3179
|
+
});
|
|
3180
|
+
TagButton.displayName = 'TagButton';
|
|
3181
|
+
|
|
3160
3182
|
var Table = function (_a) {
|
|
3161
3183
|
var children = _a.children, className = _a.className, variant = _a.variant, other = tslib.__rest(_a, ["children", "className", "variant"]);
|
|
3162
3184
|
return (React__default["default"].createElement("table", tslib.__assign({ className: classNames__default["default"]('Table', variant === 'border' && 'Table--border', className) }, other), children));
|
|
@@ -3943,6 +3965,748 @@ Notice.propTypes = {
|
|
|
3943
3965
|
icon: PropTypes__default["default"].string
|
|
3944
3966
|
};
|
|
3945
3967
|
|
|
3968
|
+
/* istanbul ignore next */
|
|
3969
|
+
var ListboxContext = React.createContext({
|
|
3970
|
+
options: [],
|
|
3971
|
+
active: null,
|
|
3972
|
+
selected: null,
|
|
3973
|
+
setOptions: function () { return null; },
|
|
3974
|
+
onSelect: function () { return null; }
|
|
3975
|
+
});
|
|
3976
|
+
function ListboxProvider(_a) {
|
|
3977
|
+
var options = _a.options, active = _a.active, selected = _a.selected, setOptions = _a.setOptions, onSelect = _a.onSelect, children = _a.children;
|
|
3978
|
+
var Provider = ListboxContext.Provider;
|
|
3979
|
+
var value = React.useMemo(function () { return ({
|
|
3980
|
+
options: options,
|
|
3981
|
+
active: active,
|
|
3982
|
+
selected: selected,
|
|
3983
|
+
setOptions: setOptions,
|
|
3984
|
+
onSelect: onSelect
|
|
3985
|
+
}); }, [options, active, selected, setOptions]);
|
|
3986
|
+
return React__default["default"].createElement(Provider, { value: value }, children);
|
|
3987
|
+
}
|
|
3988
|
+
function useListboxContext() {
|
|
3989
|
+
return React.useContext(ListboxContext);
|
|
3990
|
+
}
|
|
3991
|
+
|
|
3992
|
+
var keys = ['ArrowUp', 'ArrowDown', 'Home', 'End', 'Enter', ' '];
|
|
3993
|
+
// id for listbox options should always be defined since it should
|
|
3994
|
+
// be provide via the author, or auto-generated via the component
|
|
3995
|
+
var getOptionId = function (option) {
|
|
3996
|
+
return option.element.getAttribute('id');
|
|
3997
|
+
};
|
|
3998
|
+
var isDisabledOption = function (option) {
|
|
3999
|
+
return option.element.getAttribute('aria-disabled') === 'true';
|
|
4000
|
+
};
|
|
4001
|
+
var optionMatchesValue = function (option, value) {
|
|
4002
|
+
return typeof option.value !== null &&
|
|
4003
|
+
typeof option.value !== 'undefined' &&
|
|
4004
|
+
option.value === value;
|
|
4005
|
+
};
|
|
4006
|
+
var Listbox = React.forwardRef(function (_a, ref) {
|
|
4007
|
+
var _b = _a.as, Component = _b === void 0 ? 'ul' : _b, children = _a.children, defaultValue = _a.defaultValue, value = _a.value, _c = _a.navigation, navigation = _c === void 0 ? 'bound' : _c, onKeyDown = _a.onKeyDown, onFocus = _a.onFocus, onSelectionChange = _a.onSelectionChange, onActiveChange = _a.onActiveChange, props = tslib.__rest(_a, ["as", "children", "defaultValue", "value", "navigation", "onKeyDown", "onFocus", "onSelectionChange", "onActiveChange"]);
|
|
4008
|
+
var _d = tslib.__read(React.useState([]), 2), options = _d[0], setOptions = _d[1];
|
|
4009
|
+
var _e = tslib.__read(React.useState(null), 2), activeOption = _e[0], setActiveOption = _e[1];
|
|
4010
|
+
var _f = tslib.__read(React.useState(null), 2), selectedOption = _f[0], setSelectedOption = _f[1];
|
|
4011
|
+
var listboxRef = useSharedRef(ref);
|
|
4012
|
+
var isControlled = typeof value !== 'undefined';
|
|
4013
|
+
React.useLayoutEffect(function () {
|
|
4014
|
+
if (!isControlled && selectedOption) {
|
|
4015
|
+
return;
|
|
4016
|
+
}
|
|
4017
|
+
var listboxValue = isControlled ? value : defaultValue;
|
|
4018
|
+
var matchingOption = options.find(function (option) {
|
|
4019
|
+
return optionMatchesValue(option, listboxValue);
|
|
4020
|
+
});
|
|
4021
|
+
setSelectedOption(matchingOption || null);
|
|
4022
|
+
setActiveOption(matchingOption || null);
|
|
4023
|
+
}, [isControlled, options, value]);
|
|
4024
|
+
React.useEffect(function () {
|
|
4025
|
+
if (activeOption) {
|
|
4026
|
+
onActiveChange === null || onActiveChange === void 0 ? void 0 : onActiveChange(activeOption);
|
|
4027
|
+
}
|
|
4028
|
+
}, [activeOption]);
|
|
4029
|
+
var handleSelect = React.useCallback(function (option) {
|
|
4030
|
+
setActiveOption(option);
|
|
4031
|
+
// istanbul ignore else
|
|
4032
|
+
if (!isControlled) {
|
|
4033
|
+
setSelectedOption(option);
|
|
4034
|
+
}
|
|
4035
|
+
onSelectionChange === null || onSelectionChange === void 0 ? void 0 : onSelectionChange({
|
|
4036
|
+
target: option.element,
|
|
4037
|
+
value: option.value,
|
|
4038
|
+
previousValue: selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.value
|
|
4039
|
+
});
|
|
4040
|
+
}, [isControlled, selectedOption]);
|
|
4041
|
+
var handleKeyDown = React.useCallback(function (event) {
|
|
4042
|
+
onKeyDown === null || onKeyDown === void 0 ? void 0 : onKeyDown(event);
|
|
4043
|
+
if (!keys.includes(event.key)) {
|
|
4044
|
+
return;
|
|
4045
|
+
}
|
|
4046
|
+
event.preventDefault();
|
|
4047
|
+
var enabledOptions = options.filter(function (option) { return !isDisabledOption(option); });
|
|
4048
|
+
// istanbul ignore next
|
|
4049
|
+
if (!enabledOptions.length) {
|
|
4050
|
+
return;
|
|
4051
|
+
}
|
|
4052
|
+
var _a = tslib.__read(keys, 6), up = _a[0], down = _a[1], home = _a[2], end = _a[3], enter = _a[4], space = _a[5];
|
|
4053
|
+
var firstOption = enabledOptions[0];
|
|
4054
|
+
if (!activeOption) {
|
|
4055
|
+
setActiveOption(firstOption);
|
|
4056
|
+
return;
|
|
4057
|
+
}
|
|
4058
|
+
var lastOption = enabledOptions[enabledOptions.length - 1];
|
|
4059
|
+
var currentOption = activeOption;
|
|
4060
|
+
var currentIndex = enabledOptions.findIndex(function (_a) {
|
|
4061
|
+
var element = _a.element;
|
|
4062
|
+
return element === currentOption.element;
|
|
4063
|
+
});
|
|
4064
|
+
var allowCyclicalNavigation = navigation === 'cycle';
|
|
4065
|
+
switch (event.key) {
|
|
4066
|
+
case up:
|
|
4067
|
+
var previousOption = currentIndex === 0 && allowCyclicalNavigation
|
|
4068
|
+
? lastOption
|
|
4069
|
+
: enabledOptions[Math.max(currentIndex - 1, 0)];
|
|
4070
|
+
setActiveOption(previousOption);
|
|
4071
|
+
break;
|
|
4072
|
+
case down:
|
|
4073
|
+
var nextOption = currentIndex === enabledOptions.length - 1 &&
|
|
4074
|
+
allowCyclicalNavigation
|
|
4075
|
+
? firstOption
|
|
4076
|
+
: enabledOptions[Math.min(currentIndex + 1, enabledOptions.length - 1)];
|
|
4077
|
+
setActiveOption(nextOption);
|
|
4078
|
+
break;
|
|
4079
|
+
case home:
|
|
4080
|
+
setActiveOption(firstOption);
|
|
4081
|
+
break;
|
|
4082
|
+
case end:
|
|
4083
|
+
setActiveOption(lastOption);
|
|
4084
|
+
break;
|
|
4085
|
+
case enter:
|
|
4086
|
+
case space:
|
|
4087
|
+
activeOption && handleSelect(activeOption);
|
|
4088
|
+
break;
|
|
4089
|
+
}
|
|
4090
|
+
}, [options, activeOption, navigation]);
|
|
4091
|
+
var handleFocus = React.useCallback(function (event) {
|
|
4092
|
+
if (!activeOption && !selectedOption) {
|
|
4093
|
+
var firstOption = options.find(function (option) { return !isDisabledOption(option); });
|
|
4094
|
+
// istanbul ignore else
|
|
4095
|
+
if (firstOption) {
|
|
4096
|
+
setActiveOption(firstOption);
|
|
4097
|
+
}
|
|
4098
|
+
// istanbul ignore else
|
|
4099
|
+
}
|
|
4100
|
+
else if (event.target === listboxRef.current) {
|
|
4101
|
+
setActiveOption(selectedOption);
|
|
4102
|
+
}
|
|
4103
|
+
onFocus === null || onFocus === void 0 ? void 0 : onFocus(event);
|
|
4104
|
+
}, [options, activeOption, selectedOption]);
|
|
4105
|
+
return (React__default["default"].createElement(Component, tslib.__assign({ role: "listbox", ref: listboxRef, tabIndex: "0", onKeyDown: handleKeyDown, onFocus: handleFocus, "aria-activedescendant": activeOption ? getOptionId(activeOption) : undefined }, props),
|
|
4106
|
+
React__default["default"].createElement(ListboxProvider, { options: options, active: activeOption, selected: selectedOption, setOptions: setOptions, onSelect: handleSelect }, children)));
|
|
4107
|
+
});
|
|
4108
|
+
Listbox.displayName = 'Listbox';
|
|
4109
|
+
|
|
4110
|
+
function isElementPreceding(a, b) {
|
|
4111
|
+
return !!(b.compareDocumentPosition(a) & Node.DOCUMENT_POSITION_PRECEDING);
|
|
4112
|
+
}
|
|
4113
|
+
var ListboxOption = React.forwardRef(function (_a, ref) {
|
|
4114
|
+
var _b;
|
|
4115
|
+
var _c;
|
|
4116
|
+
var propId = _a.id, className = _a.className, _d = _a.as, Component = _d === void 0 ? 'li' : _d, children = _a.children, value = _a.value, disabled = _a.disabled, _e = _a.activeClass, activeClass = _e === void 0 ? 'ListboxOption--active' : _e, onClick = _a.onClick, props = tslib.__rest(_a, ["id", "className", "as", "children", "value", "disabled", "activeClass", "onClick"]);
|
|
4117
|
+
var _f = useListboxContext(), active = _f.active, selected = _f.selected, setOptions = _f.setOptions, onSelect = _f.onSelect;
|
|
4118
|
+
var listboxOptionRef = useSharedRef(ref);
|
|
4119
|
+
var _g = tslib.__read(propId ? [propId] : nextId.useId(1, 'listbox-option'), 1), id = _g[0];
|
|
4120
|
+
var isActive = active !== null && active.element === listboxOptionRef.current;
|
|
4121
|
+
var isSelected = selected !== null && selected.element === listboxOptionRef.current;
|
|
4122
|
+
var optionValue = typeof value !== 'undefined'
|
|
4123
|
+
? value
|
|
4124
|
+
: (_c = listboxOptionRef.current) === null || _c === void 0 ? void 0 : _c.innerText;
|
|
4125
|
+
React.useEffect(function () {
|
|
4126
|
+
var element = listboxOptionRef.current;
|
|
4127
|
+
setOptions(function (options) {
|
|
4128
|
+
var e_1, _a;
|
|
4129
|
+
var option = { element: element, value: optionValue };
|
|
4130
|
+
// istanbul ignore next
|
|
4131
|
+
if (!element)
|
|
4132
|
+
return options;
|
|
4133
|
+
// Elements are frequently appended, so check to see if the newly rendered
|
|
4134
|
+
// element follows the last element first before any other checks
|
|
4135
|
+
if (!options.length ||
|
|
4136
|
+
isElementPreceding(options[options.length - 1].element, option.element)) {
|
|
4137
|
+
return tslib.__spreadArray(tslib.__spreadArray([], tslib.__read(options), false), [option], false);
|
|
4138
|
+
}
|
|
4139
|
+
try {
|
|
4140
|
+
for (var options_1 = tslib.__values(options), options_1_1 = options_1.next(); !options_1_1.done; options_1_1 = options_1.next()) {
|
|
4141
|
+
var opt = options_1_1.value;
|
|
4142
|
+
if (isElementPreceding(element, opt.element)) {
|
|
4143
|
+
var index = options.indexOf(opt);
|
|
4144
|
+
return tslib.__spreadArray(tslib.__spreadArray(tslib.__spreadArray([], tslib.__read(options.slice(0, index)), false), [
|
|
4145
|
+
option
|
|
4146
|
+
], false), tslib.__read(options.slice(index)), false);
|
|
4147
|
+
}
|
|
4148
|
+
}
|
|
4149
|
+
}
|
|
4150
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
4151
|
+
finally {
|
|
4152
|
+
try {
|
|
4153
|
+
if (options_1_1 && !options_1_1.done && (_a = options_1.return)) _a.call(options_1);
|
|
4154
|
+
}
|
|
4155
|
+
finally { if (e_1) throw e_1.error; }
|
|
4156
|
+
}
|
|
4157
|
+
// istanbul ignore next
|
|
4158
|
+
// this should never happen, but just in case fall back to options
|
|
4159
|
+
return options;
|
|
4160
|
+
});
|
|
4161
|
+
return function () {
|
|
4162
|
+
setOptions(function (opts) { return opts.filter(function (opt) { return opt.element !== element; }); });
|
|
4163
|
+
};
|
|
4164
|
+
}, [optionValue]);
|
|
4165
|
+
var handleClick = React.useCallback(function (event) {
|
|
4166
|
+
if (disabled) {
|
|
4167
|
+
return;
|
|
4168
|
+
}
|
|
4169
|
+
onSelect({ element: listboxOptionRef.current, value: optionValue });
|
|
4170
|
+
onClick === null || onClick === void 0 ? void 0 : onClick(event);
|
|
4171
|
+
}, [optionValue]);
|
|
4172
|
+
return (React__default["default"].createElement(Component, tslib.__assign({ id: id, className: classNames__default["default"](className, (_b = {},
|
|
4173
|
+
_b[activeClass] = isActive,
|
|
4174
|
+
_b)), role: "option", ref: listboxOptionRef, "aria-disabled": typeof disabled === 'boolean' ? disabled : undefined, "aria-selected": isSelected, onClick: handleClick }, props), children));
|
|
4175
|
+
});
|
|
4176
|
+
ListboxOption.displayName = 'ListboxOption';
|
|
4177
|
+
|
|
4178
|
+
var ListboxGroup = React.forwardRef(function (_a, ref) {
|
|
4179
|
+
var _b = _a.as, Component = _b === void 0 ? 'ul' : _b, children = _a.children, propId = _a.id, label = _a.label, groupLabelProps = _a.groupLabelProps, props = tslib.__rest(_a, ["as", "children", "id", "label", "groupLabelProps"]);
|
|
4180
|
+
var _c = tslib.__read(propId ? [propId] : nextId.useId(1, 'listbox-group-label'), 1), id = _c[0];
|
|
4181
|
+
return (React__default["default"].createElement(Component, tslib.__assign({ role: "group", ref: ref, "aria-labelledby": id }, props),
|
|
4182
|
+
React__default["default"].createElement("li", tslib.__assign({ role: "presentation", id: id }, groupLabelProps), label),
|
|
4183
|
+
children));
|
|
4184
|
+
});
|
|
4185
|
+
ListboxGroup.displayName = 'ListboxGroup';
|
|
4186
|
+
|
|
4187
|
+
/* istanbul ignore next */
|
|
4188
|
+
var ComboboxContext = React.createContext({
|
|
4189
|
+
autocomplete: 'manual',
|
|
4190
|
+
inputValue: undefined,
|
|
4191
|
+
selectedValue: undefined,
|
|
4192
|
+
matches: true,
|
|
4193
|
+
matchingOptions: new Map(),
|
|
4194
|
+
setMatchingOptions: function () { return null; }
|
|
4195
|
+
});
|
|
4196
|
+
function ComboboxProvider(_a) {
|
|
4197
|
+
var autocomplete = _a.autocomplete, inputValue = _a.inputValue, selectedValue = _a.selectedValue, matches = _a.matches, matchingOptions = _a.matchingOptions, setMatchingOptions = _a.setMatchingOptions, children = _a.children;
|
|
4198
|
+
var Provider = ComboboxContext.Provider;
|
|
4199
|
+
var contextValue = React.useMemo(function () { return ({
|
|
4200
|
+
autocomplete: autocomplete,
|
|
4201
|
+
inputValue: inputValue,
|
|
4202
|
+
selectedValue: selectedValue,
|
|
4203
|
+
matches: typeof matches === 'function' && !!inputValue
|
|
4204
|
+
? function (value) { return matches(inputValue, value); }
|
|
4205
|
+
: true,
|
|
4206
|
+
matchingOptions: matchingOptions,
|
|
4207
|
+
setMatchingOptions: setMatchingOptions
|
|
4208
|
+
}); }, [
|
|
4209
|
+
autocomplete,
|
|
4210
|
+
inputValue,
|
|
4211
|
+
selectedValue,
|
|
4212
|
+
matches,
|
|
4213
|
+
matchingOptions,
|
|
4214
|
+
setMatchingOptions
|
|
4215
|
+
]);
|
|
4216
|
+
return React__default["default"].createElement(Provider, { value: contextValue }, children);
|
|
4217
|
+
}
|
|
4218
|
+
function useComboboxContext() {
|
|
4219
|
+
return React.useContext(ComboboxContext);
|
|
4220
|
+
}
|
|
4221
|
+
|
|
4222
|
+
/**
|
|
4223
|
+
* When a component needs to track intersection via a ref, useIntersectionRef
|
|
4224
|
+
* will return a ref object containing the results from IntersectionObserver
|
|
4225
|
+
* for the current intersection entry.
|
|
4226
|
+
*
|
|
4227
|
+
* @example
|
|
4228
|
+
* const elementRef = useRef<HTMLElement>()
|
|
4229
|
+
* const intersectionRef = useIntersectionRef<HTMLElement>(elementRef)
|
|
4230
|
+
* return <span ref={elementRef}>...</span>
|
|
4231
|
+
*/
|
|
4232
|
+
function useIntersectionRef(element, intersectionObserverOptions) {
|
|
4233
|
+
if (intersectionObserverOptions === void 0) { intersectionObserverOptions = {
|
|
4234
|
+
root: null,
|
|
4235
|
+
threshold: 1.0
|
|
4236
|
+
}; }
|
|
4237
|
+
var intersectionRef = React.useRef(null);
|
|
4238
|
+
React.useEffect(function () {
|
|
4239
|
+
// istanbul ignore else
|
|
4240
|
+
if ('IntersectionObserver' in globalThis &&
|
|
4241
|
+
typeof IntersectionObserver === 'function') {
|
|
4242
|
+
if (typeof element === 'undefined' || element === null) {
|
|
4243
|
+
return;
|
|
4244
|
+
}
|
|
4245
|
+
if (!(element instanceof HTMLElement) &&
|
|
4246
|
+
!(element.current instanceof HTMLElement)) {
|
|
4247
|
+
console.warn('An element or ref was provided to useIntersectionRef that was not an HTMLElement.');
|
|
4248
|
+
return;
|
|
4249
|
+
}
|
|
4250
|
+
var handleIntersection = function (_a) {
|
|
4251
|
+
var _b = tslib.__read(_a, 1), entry = _b[0];
|
|
4252
|
+
intersectionRef.current = entry;
|
|
4253
|
+
};
|
|
4254
|
+
var observer_1 = new IntersectionObserver(handleIntersection, intersectionObserverOptions);
|
|
4255
|
+
observer_1.observe(element instanceof HTMLElement ? element : element.current);
|
|
4256
|
+
return function () {
|
|
4257
|
+
observer_1.disconnect();
|
|
4258
|
+
};
|
|
4259
|
+
}
|
|
4260
|
+
}, [element]);
|
|
4261
|
+
return intersectionRef;
|
|
4262
|
+
}
|
|
4263
|
+
|
|
4264
|
+
var ComboboxMatch = function (_a) {
|
|
4265
|
+
var text = _a.children;
|
|
4266
|
+
var inputValue = useComboboxContext().inputValue;
|
|
4267
|
+
if (!(inputValue === null || inputValue === void 0 ? void 0 : inputValue.length)) {
|
|
4268
|
+
return React__default["default"].createElement("span", null, text);
|
|
4269
|
+
}
|
|
4270
|
+
var matchStart = text.toLowerCase().indexOf(inputValue === null || inputValue === void 0 ? void 0 : inputValue.toLowerCase());
|
|
4271
|
+
if (matchStart === -1) {
|
|
4272
|
+
return React__default["default"].createElement("span", null, text);
|
|
4273
|
+
}
|
|
4274
|
+
var matchLength = inputValue.length;
|
|
4275
|
+
var matchBefore = text.substring(0, matchStart);
|
|
4276
|
+
var match = text.substring(matchStart, matchLength + matchStart);
|
|
4277
|
+
var matchAfter = text.substring(matchStart + matchLength);
|
|
4278
|
+
return (React__default["default"].createElement(React__default["default"].Fragment, null,
|
|
4279
|
+
React__default["default"].createElement("span", null, matchBefore),
|
|
4280
|
+
React__default["default"].createElement("em", { className: "ComboboxOption__match" }, match),
|
|
4281
|
+
React__default["default"].createElement("span", null, matchAfter)));
|
|
4282
|
+
};
|
|
4283
|
+
var ComboboxOption = React.forwardRef(function (_a, ref) {
|
|
4284
|
+
var className = _a.className, children = _a.children, disabled = _a.disabled, propId = _a.id, description = _a.description, propValue = _a.value, props = tslib.__rest(_a, ["className", "children", "disabled", "id", "description", "value"]);
|
|
4285
|
+
var _b = tslib.__read(propId ? [propId] : nextId.useId(1, 'combobox-option'), 1), id = _b[0];
|
|
4286
|
+
var _c = useListboxContext(), selected = _c.selected, active = _c.active;
|
|
4287
|
+
var _d = useComboboxContext(), matches = _d.matches, setMatchingOptions = _d.setMatchingOptions;
|
|
4288
|
+
var comboboxOptionRef = useSharedRef(ref);
|
|
4289
|
+
var intersectionRef = useIntersectionRef(comboboxOptionRef, {
|
|
4290
|
+
root: null,
|
|
4291
|
+
threshold: 1.0
|
|
4292
|
+
});
|
|
4293
|
+
var isActive = !!(active === null || active === void 0 ? void 0 : active.element) && active.element === comboboxOptionRef.current;
|
|
4294
|
+
var isSelected = !!(selected === null || selected === void 0 ? void 0 : selected.element) && selected.element === comboboxOptionRef.current;
|
|
4295
|
+
var isMatching = (typeof matches === 'boolean' && matches) ||
|
|
4296
|
+
(typeof matches === 'function' && matches(children));
|
|
4297
|
+
// istanbul ignore next
|
|
4298
|
+
React.useLayoutEffect(function () {
|
|
4299
|
+
var intersectionEntry = intersectionRef.current;
|
|
4300
|
+
if (!intersectionEntry || !isActive) {
|
|
4301
|
+
return;
|
|
4302
|
+
}
|
|
4303
|
+
var rect = comboboxOptionRef.current.getBoundingClientRect();
|
|
4304
|
+
var isInViewport = rect.top >= 0 &&
|
|
4305
|
+
rect.left >= 0 &&
|
|
4306
|
+
rect.bottom <= window.innerHeight &&
|
|
4307
|
+
rect.right <= window.innerWidth;
|
|
4308
|
+
if (!isInViewport || !intersectionEntry.isIntersecting) {
|
|
4309
|
+
comboboxOptionRef.current.scrollIntoView({
|
|
4310
|
+
inline: 'nearest',
|
|
4311
|
+
block: rect.top <= 0 ? 'end' : 'nearest'
|
|
4312
|
+
});
|
|
4313
|
+
}
|
|
4314
|
+
}, [isActive]);
|
|
4315
|
+
React.useEffect(function () {
|
|
4316
|
+
if (isMatching) {
|
|
4317
|
+
setMatchingOptions(function (options) {
|
|
4318
|
+
return new Map(options.set(comboboxOptionRef.current, {
|
|
4319
|
+
value: children,
|
|
4320
|
+
selected: isSelected
|
|
4321
|
+
}));
|
|
4322
|
+
});
|
|
4323
|
+
}
|
|
4324
|
+
return function () {
|
|
4325
|
+
setMatchingOptions(function (options) {
|
|
4326
|
+
options.forEach(function (_value, element) {
|
|
4327
|
+
// istanbul ignore else
|
|
4328
|
+
if (!element.isConnected) {
|
|
4329
|
+
options.delete(element);
|
|
4330
|
+
}
|
|
4331
|
+
});
|
|
4332
|
+
return new Map(options);
|
|
4333
|
+
});
|
|
4334
|
+
};
|
|
4335
|
+
}, [isMatching, isSelected]);
|
|
4336
|
+
if (!isMatching) {
|
|
4337
|
+
return null;
|
|
4338
|
+
}
|
|
4339
|
+
return (React__default["default"].createElement(ListboxOption, tslib.__assign({ as: "li", className: classNames__default["default"]('ComboboxOption', className, {
|
|
4340
|
+
'ComboboxOption--disabled': disabled
|
|
4341
|
+
}), activeClass: "ComboboxOption--active", ref: comboboxOptionRef, disabled: disabled, id: id, value: propValue }, props),
|
|
4342
|
+
React__default["default"].createElement("span", null,
|
|
4343
|
+
React__default["default"].createElement(ComboboxMatch, null, children),
|
|
4344
|
+
description && (React__default["default"].createElement("div", { className: "ComboboxOption__description" }, description))),
|
|
4345
|
+
isSelected ? React__default["default"].createElement(Icon, { type: "check-solid" }) : null));
|
|
4346
|
+
});
|
|
4347
|
+
ComboboxOption.displayName = 'ComboboxOption';
|
|
4348
|
+
|
|
4349
|
+
// Event Keys
|
|
4350
|
+
var _a = tslib.__read(['Enter', 'Escape', 'Home', 'End'], 4), Enter = _a[0], Escape = _a[1], Home = _a[2], End = _a[3];
|
|
4351
|
+
var defaultAutoCompleteMatches = function (inputValue, value) {
|
|
4352
|
+
// istanbul ignore if
|
|
4353
|
+
if (!value) {
|
|
4354
|
+
return true;
|
|
4355
|
+
}
|
|
4356
|
+
return value.toLowerCase().includes(inputValue.toLowerCase());
|
|
4357
|
+
};
|
|
4358
|
+
var ComboboxNoResults = function (_a) {
|
|
4359
|
+
var children = _a.children;
|
|
4360
|
+
return (React__default["default"].createElement("div", { className: "ComboboxListbox__empty", role: "alert", "aria-live": "polite" }, children || 'No results found.'));
|
|
4361
|
+
};
|
|
4362
|
+
var Combobox = React.forwardRef(function (_a, ref) {
|
|
4363
|
+
var propId = _a.id, className = _a.className, label = _a.label, children = _a.children, _b = _a.options, options = _b === void 0 ? [] : _b, propValue = _a.value, defaultValue = _a.defaultValue, _c = _a.requiredText, requiredText = _c === void 0 ? 'Required' : _c, error = _a.error, _d = _a.autocomplete, autocomplete = _d === void 0 ? 'manual' : _d, onSelectionChange = _a.onSelectionChange, onActiveChange = _a.onActiveChange, onChange = _a.onChange, onKeyDown = _a.onKeyDown, onFocus = _a.onFocus, onBlur = _a.onBlur, renderNoResults = _a.renderNoResults, portal = _a.portal, props = tslib.__rest(_a, ["id", "className", "label", "children", "options", "value", "defaultValue", "requiredText", "error", "autocomplete", "onSelectionChange", "onActiveChange", "onChange", "onKeyDown", "onFocus", "onBlur", "renderNoResults", "portal"]);
|
|
4364
|
+
var _e = tslib.__read(React.useState(defaultValue || propValue || ''), 2), value = _e[0], setValue = _e[1];
|
|
4365
|
+
var _f = tslib.__read(React.useState(new Map()), 2), matchingOptions = _f[0], setMatchingOptions = _f[1];
|
|
4366
|
+
var _g = tslib.__read(React.useState(value || ''), 2), selectedValue = _g[0], setSelectedValue = _g[1];
|
|
4367
|
+
var _h = tslib.__read(React.useState(false), 2), open = _h[0], setOpen = _h[1];
|
|
4368
|
+
var _j = tslib.__read(React.useState(null), 2), activeDescendant = _j[0], setActiveDescendant = _j[1];
|
|
4369
|
+
var _k = tslib.__read(propId ? [propId] : nextId.useId(1, 'combobox'), 1), id = _k[0];
|
|
4370
|
+
var comboboxRef = useSharedRef(ref);
|
|
4371
|
+
var inputRef = React.useRef(null);
|
|
4372
|
+
var listboxRef = React.useRef(null);
|
|
4373
|
+
var isControlled = typeof propValue !== 'undefined';
|
|
4374
|
+
var isRequired = !!props.required;
|
|
4375
|
+
var isAutoComplete = autocomplete !== 'none';
|
|
4376
|
+
var hasError = !!error;
|
|
4377
|
+
var comboboxOptions = children ||
|
|
4378
|
+
options.map(function (option, index) { return (React__default["default"].createElement(ComboboxOption, { key: option.key || index, id: "".concat(id, "-option-").concat(index + 1), description: option.description }, option.label)); });
|
|
4379
|
+
var triggerListboxKeyDown = React__default["default"].useCallback(function (key) {
|
|
4380
|
+
var _a;
|
|
4381
|
+
(_a = listboxRef.current) === null || _a === void 0 ? void 0 : _a.dispatchEvent(new KeyboardEvent('keydown', {
|
|
4382
|
+
key: key,
|
|
4383
|
+
bubbles: true,
|
|
4384
|
+
cancelable: true
|
|
4385
|
+
}));
|
|
4386
|
+
}, [listboxRef]);
|
|
4387
|
+
React.useEffect(function () {
|
|
4388
|
+
if (!isAutoComplete) {
|
|
4389
|
+
return;
|
|
4390
|
+
}
|
|
4391
|
+
if (!open && selectedValue && value !== selectedValue) {
|
|
4392
|
+
setValue(selectedValue);
|
|
4393
|
+
}
|
|
4394
|
+
if (!open) {
|
|
4395
|
+
setActiveDescendant(null);
|
|
4396
|
+
}
|
|
4397
|
+
if (open && autocomplete === 'automatic' && !selectedValue) {
|
|
4398
|
+
// Fire an Home keydown event on listbox to ensure the first item is selected
|
|
4399
|
+
triggerListboxKeyDown(Home);
|
|
4400
|
+
}
|
|
4401
|
+
}, [open]);
|
|
4402
|
+
React.useEffect(function () {
|
|
4403
|
+
if (autocomplete === 'manual') {
|
|
4404
|
+
setActiveDescendant(null);
|
|
4405
|
+
}
|
|
4406
|
+
else if (autocomplete === 'automatic' &&
|
|
4407
|
+
matchingOptions.size &&
|
|
4408
|
+
!selectedValue) {
|
|
4409
|
+
// Fire a home keydown event on listbox to ensure the first item is selected
|
|
4410
|
+
requestAnimationFrame(function () {
|
|
4411
|
+
triggerListboxKeyDown(Home);
|
|
4412
|
+
});
|
|
4413
|
+
}
|
|
4414
|
+
}, [matchingOptions]);
|
|
4415
|
+
var handleFocus = React.useCallback(function (event) {
|
|
4416
|
+
onFocus === null || onFocus === void 0 ? void 0 : onFocus(event);
|
|
4417
|
+
// istanbul ignore else
|
|
4418
|
+
if (!event.defaultPrevented) {
|
|
4419
|
+
setOpen(true);
|
|
4420
|
+
if (selectedValue && value === selectedValue && isAutoComplete) {
|
|
4421
|
+
setValue('');
|
|
4422
|
+
}
|
|
4423
|
+
}
|
|
4424
|
+
}, [onFocus, value, selectedValue]);
|
|
4425
|
+
var handleInputClick = React.useCallback(function (event) {
|
|
4426
|
+
var _a;
|
|
4427
|
+
setOpen(true);
|
|
4428
|
+
if (selectedValue && value === selectedValue && isAutoComplete) {
|
|
4429
|
+
setValue('');
|
|
4430
|
+
}
|
|
4431
|
+
if (event.target !== inputRef.current) {
|
|
4432
|
+
// ensure focus is set on the input field
|
|
4433
|
+
(_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
4434
|
+
}
|
|
4435
|
+
}, [value, selectedValue]);
|
|
4436
|
+
var handleComboboxOptionMouseDown = React.useCallback(function (event) {
|
|
4437
|
+
// prevent blur from triggering when activating combobox options
|
|
4438
|
+
event.preventDefault();
|
|
4439
|
+
}, []);
|
|
4440
|
+
var handleComboboxOptionClick = React.useCallback(function () {
|
|
4441
|
+
var _a;
|
|
4442
|
+
// maintain focus on the input
|
|
4443
|
+
(_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
4444
|
+
}, []);
|
|
4445
|
+
var handleBlur = React.useCallback(function (event) {
|
|
4446
|
+
var _a;
|
|
4447
|
+
onBlur === null || onBlur === void 0 ? void 0 : onBlur(event);
|
|
4448
|
+
setOpen(false);
|
|
4449
|
+
if (autocomplete === 'automatic' && activeDescendant) {
|
|
4450
|
+
var stringValue = ((_a = activeDescendant.value) === null || _a === void 0 ? void 0 : _a.toString()) ||
|
|
4451
|
+
/* istanbul ignore next: default value */ '';
|
|
4452
|
+
setValue(stringValue);
|
|
4453
|
+
setSelectedValue(stringValue);
|
|
4454
|
+
}
|
|
4455
|
+
}, [autocomplete, activeDescendant, onBlur]);
|
|
4456
|
+
var handleKeyDown = React.useCallback(function (event) {
|
|
4457
|
+
onKeyDown === null || onKeyDown === void 0 ? void 0 : onKeyDown(event);
|
|
4458
|
+
var enterKeypress = event.key === Enter;
|
|
4459
|
+
var escKeypress = event.key === Escape;
|
|
4460
|
+
var arrowKeypress = ['ArrowDown', 'ArrowUp'].includes(event.key);
|
|
4461
|
+
if ([Home, End].includes(event.key)) {
|
|
4462
|
+
// prevent the page from scrolling and allow start/end option activation
|
|
4463
|
+
event.preventDefault();
|
|
4464
|
+
}
|
|
4465
|
+
if (escKeypress) {
|
|
4466
|
+
setOpen(false);
|
|
4467
|
+
return;
|
|
4468
|
+
}
|
|
4469
|
+
// Selection should not open the listbox or be
|
|
4470
|
+
// forwarded to the listbox component when closed
|
|
4471
|
+
if (enterKeypress && !open) {
|
|
4472
|
+
return;
|
|
4473
|
+
}
|
|
4474
|
+
setOpen(true);
|
|
4475
|
+
if (!open && arrowKeypress && selectedValue && isAutoComplete) {
|
|
4476
|
+
// If the user opens the combobox again with a selected value
|
|
4477
|
+
// just clear out the field to restore filtering capabilities
|
|
4478
|
+
setValue('');
|
|
4479
|
+
}
|
|
4480
|
+
// Space should not trigger selection since the user could be typing
|
|
4481
|
+
// a value for autocompletion. Additionally when not open and there's
|
|
4482
|
+
// an active descendent we do not want to forward keydown events.
|
|
4483
|
+
if (event.key === ' ' ||
|
|
4484
|
+
(!open && activeDescendant) ||
|
|
4485
|
+
(enterKeypress && !activeDescendant)) {
|
|
4486
|
+
return;
|
|
4487
|
+
}
|
|
4488
|
+
// forward input events to listbox
|
|
4489
|
+
triggerListboxKeyDown(event.key);
|
|
4490
|
+
// Close combobox with keyboard selections
|
|
4491
|
+
if (enterKeypress && activeDescendant) {
|
|
4492
|
+
setOpen(false);
|
|
4493
|
+
}
|
|
4494
|
+
}, [onKeyDown, isAutoComplete, open, selectedValue, activeDescendant]);
|
|
4495
|
+
React.useEffect(function () {
|
|
4496
|
+
if (typeof propValue !== 'undefined') {
|
|
4497
|
+
setValue(propValue);
|
|
4498
|
+
}
|
|
4499
|
+
}, [propValue]);
|
|
4500
|
+
var handleChange = React.useCallback(function (event) {
|
|
4501
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(event);
|
|
4502
|
+
// istanbul ignore else
|
|
4503
|
+
if (!isControlled) {
|
|
4504
|
+
setValue(event.target.value);
|
|
4505
|
+
}
|
|
4506
|
+
}, [isControlled, onChange]);
|
|
4507
|
+
var handleSelectionChange = React.useCallback(function (_a) {
|
|
4508
|
+
var target = _a.target, listboxValue = _a.value, previousValue = _a.previousValue;
|
|
4509
|
+
var stringValue = (listboxValue === null || listboxValue === void 0 ? void 0 : listboxValue.toString()) || /* istanbul ignore next */ '';
|
|
4510
|
+
// istanbul ignore else
|
|
4511
|
+
if (!isControlled) {
|
|
4512
|
+
setValue(stringValue);
|
|
4513
|
+
}
|
|
4514
|
+
setSelectedValue(stringValue);
|
|
4515
|
+
onSelectionChange === null || onSelectionChange === void 0 ? void 0 : onSelectionChange({
|
|
4516
|
+
target: target,
|
|
4517
|
+
value: stringValue,
|
|
4518
|
+
previousValue: previousValue === null || previousValue === void 0 ? void 0 : previousValue.toString()
|
|
4519
|
+
});
|
|
4520
|
+
setOpen(false);
|
|
4521
|
+
}, [isControlled, onSelectionChange]);
|
|
4522
|
+
var handleActiveChange = React.useCallback(function (option) {
|
|
4523
|
+
// istanbul ignore else
|
|
4524
|
+
if (option.element) {
|
|
4525
|
+
setActiveDescendant(option);
|
|
4526
|
+
}
|
|
4527
|
+
onActiveChange === null || onActiveChange === void 0 ? void 0 : onActiveChange(option);
|
|
4528
|
+
}, []);
|
|
4529
|
+
var NoMatchingOptions = React__default["default"].useMemo(function () {
|
|
4530
|
+
return React__default["default"].isValidElement(renderNoResults)
|
|
4531
|
+
? function () { return React__default["default"].createElement(ComboboxNoResults, null, renderNoResults); }
|
|
4532
|
+
: typeof renderNoResults === 'function'
|
|
4533
|
+
? function () { return React__default["default"].createElement(ComboboxNoResults, null, renderNoResults()); }
|
|
4534
|
+
: ComboboxNoResults;
|
|
4535
|
+
}, [renderNoResults]);
|
|
4536
|
+
var noMatchingOptions = !!(value === null || value === void 0 ? void 0 : value.length) && !matchingOptions.size && (React__default["default"].createElement(NoMatchingOptions, null));
|
|
4537
|
+
var comboboxListbox = (React__default["default"].createElement(Listbox, { className: classNames__default["default"]('Combobox__listbox', {
|
|
4538
|
+
'Combobox__listbox--open': open
|
|
4539
|
+
}), role: "listbox", "aria-labelledby": "".concat(id, "-label"), id: "".concat(id, "-listbox"), value: selectedValue, onMouseDown: handleComboboxOptionMouseDown, onClick: handleComboboxOptionClick, onSelectionChange: handleSelectionChange, onActiveChange: handleActiveChange, ref: listboxRef, tabIndex: undefined, "aria-activedescendant": "" },
|
|
4540
|
+
comboboxOptions,
|
|
4541
|
+
noMatchingOptions));
|
|
4542
|
+
return (React__default["default"].createElement("div", { id: id, className: classNames__default["default"]('Combobox', className), ref: comboboxRef },
|
|
4543
|
+
React__default["default"].createElement("label", { className: classNames__default["default"]('Field__label', {
|
|
4544
|
+
'Field__label--is-required': isRequired,
|
|
4545
|
+
'Field__label--has-error': hasError
|
|
4546
|
+
}), id: "".concat(id, "-label"), htmlFor: "".concat(id, "-input") },
|
|
4547
|
+
React__default["default"].createElement("span", null, label),
|
|
4548
|
+
isRequired && (React__default["default"].createElement("span", { className: "Field__required-text" }, requiredText))),
|
|
4549
|
+
React__default["default"].createElement("div", { className: classNames__default["default"]('Combobox__input', {
|
|
4550
|
+
'Combobox__input--error': hasError
|
|
4551
|
+
}),
|
|
4552
|
+
// We're handling click here to open the listbox when the wrapping element is clicked,
|
|
4553
|
+
// there's already keyboard handlers to open the listbox on the input element
|
|
4554
|
+
onClick: handleInputClick },
|
|
4555
|
+
React__default["default"].createElement("input", tslib.__assign({ type: "text", id: "".concat(id, "-input"), ref: inputRef, value: value, role: "combobox", "aria-autocomplete": !isAutoComplete ? 'none' : 'list', "aria-controls": "".concat(id, "-listbox"), "aria-expanded": open, "aria-haspopup": "listbox", "aria-activedescendant": open && activeDescendant ? activeDescendant.element.id : undefined }, props, { onChange: handleChange, onKeyDown: handleKeyDown, onFocus: handleFocus, onBlur: handleBlur })),
|
|
4556
|
+
React__default["default"].createElement("span", { className: "Combobox__arrow" })),
|
|
4557
|
+
React__default["default"].createElement(ComboboxProvider, { autocomplete: autocomplete, inputValue: value, selectedValue: selectedValue, matches: !isAutoComplete || defaultAutoCompleteMatches, matchingOptions: matchingOptions, setMatchingOptions: setMatchingOptions }, portal
|
|
4558
|
+
? reactDom.createPortal(comboboxListbox, portal instanceof HTMLElement
|
|
4559
|
+
? portal
|
|
4560
|
+
: portal.current ||
|
|
4561
|
+
/* istanbul ignore next: default fallback value */ document.body)
|
|
4562
|
+
: comboboxListbox),
|
|
4563
|
+
hasError && (React__default["default"].createElement("div", { className: "Error", id: "".concat(id, "-error") }, error))));
|
|
4564
|
+
});
|
|
4565
|
+
Combobox.displayName = 'Combobox';
|
|
4566
|
+
|
|
4567
|
+
var ComboboxGroup = React.forwardRef(function (_a, ref) {
|
|
4568
|
+
var className = _a.className, children = _a.children, label = _a.label, props = tslib.__rest(_a, ["className", "children", "label"]);
|
|
4569
|
+
var _b = useComboboxContext(), inputValue = _b.inputValue, autocomplete = _b.autocomplete, matchingOptions = _b.matchingOptions;
|
|
4570
|
+
var comboboxGroupRef = useSharedRef(ref);
|
|
4571
|
+
// istanbul ignore next
|
|
4572
|
+
var showGroup = React.useMemo(function () {
|
|
4573
|
+
if (autocomplete === 'none' || !(inputValue === null || inputValue === void 0 ? void 0 : inputValue.length)) {
|
|
4574
|
+
return true;
|
|
4575
|
+
}
|
|
4576
|
+
var elements = Array.from(matchingOptions.keys());
|
|
4577
|
+
return !!elements.find(function (element) { var _a; return (_a = comboboxGroupRef.current) === null || _a === void 0 ? void 0 : _a.contains(element); });
|
|
4578
|
+
}, [inputValue, autocomplete, matchingOptions]);
|
|
4579
|
+
return (React__default["default"].createElement(ListboxGroup, tslib.__assign({ as: "ul", className: classNames__default["default"]('ComboboxGroup', className, {
|
|
4580
|
+
'ComboboxGroup--hidden': !showGroup
|
|
4581
|
+
}), "aria-hidden": !showGroup, ref: comboboxGroupRef, label: label, groupLabelProps: { className: 'ComboboxGroup__label' } }, props), children));
|
|
4582
|
+
});
|
|
4583
|
+
ComboboxGroup.displayName = 'ComboboxGroup';
|
|
4584
|
+
|
|
4585
|
+
var PromptPopoverContent = function (_a) {
|
|
4586
|
+
var onClose = _a.onClose, _b = _a.applyButtonText, applyButtonText = _b === void 0 ? 'Apply' : _b, onApply = _a.onApply, _c = _a.closeButtonText, closeButtonText = _c === void 0 ? 'Close' : _c, infoText = _a.infoText, infoTextId = _a.infoTextId;
|
|
4587
|
+
return (React__default["default"].createElement(React__default["default"].Fragment, null,
|
|
4588
|
+
React__default["default"].createElement("span", { id: infoTextId }, infoText),
|
|
4589
|
+
React__default["default"].createElement(Button, { className: "Popover__apply", onClick: onApply, thin: true }, applyButtonText),
|
|
4590
|
+
React__default["default"].createElement(Button, { className: "Popover__close", variant: "secondary", onClick: onClose, thin: true }, closeButtonText)));
|
|
4591
|
+
};
|
|
4592
|
+
var Popover = React.forwardRef(function (_a, ref) {
|
|
4593
|
+
var propId = _a.id, _b = _a.placement, initialPlacement = _b === void 0 ? 'auto' : _b, children = _a.children, portal = _a.portal, target = _a.target, _c = _a.variant, variant = _c === void 0 ? 'custom' : _c, _d = _a.show, show = _d === void 0 ? false : _d, onClose = _a.onClose, className = _a.className, applyButtonText = _a.applyButtonText, closeButtonText = _a.closeButtonText, infoText = _a.infoText, onApply = _a.onApply, props = tslib.__rest(_a, ["id", "placement", "children", "portal", "target", "variant", "show", "onClose", "className", "applyButtonText", "closeButtonText", "infoText", "onApply"]);
|
|
4594
|
+
var _e = tslib.__read(propId ? [propId] : nextId.useId(1, 'popover'), 1), id = _e[0];
|
|
4595
|
+
var _f = tslib.__read(React.useState(null), 2), targetElement = _f[0], setTargetElement = _f[1];
|
|
4596
|
+
var _g = tslib.__read(React.useState(null), 2), isolator = _g[0], setIsolator = _g[1];
|
|
4597
|
+
var popoverRef = useSharedRef(ref);
|
|
4598
|
+
var _h = tslib.__read(React.useState(null), 2), arrowElement = _h[0], setArrowElement = _h[1];
|
|
4599
|
+
var _j = reactPopper.usePopper(targetElement, popoverRef === null || popoverRef === void 0 ? void 0 : popoverRef.current, {
|
|
4600
|
+
placement: initialPlacement,
|
|
4601
|
+
modifiers: [
|
|
4602
|
+
{ name: 'preventOverflow', options: { padding: 8 } },
|
|
4603
|
+
{ name: 'flip' },
|
|
4604
|
+
{ name: 'offset', options: { offset: [0, 8] } },
|
|
4605
|
+
{ name: 'arrow', options: { padding: 5, element: arrowElement } }
|
|
4606
|
+
]
|
|
4607
|
+
}), styles = _j.styles, attributes = _j.attributes;
|
|
4608
|
+
var placement = (attributes.popper &&
|
|
4609
|
+
attributes.popper['data-popper-placement']) ||
|
|
4610
|
+
initialPlacement;
|
|
4611
|
+
var additionalProps = variant === 'prompt' ? { 'aria-labelledby': "".concat(id, "-label") } : {};
|
|
4612
|
+
// Keep targetElement in sync with target prop
|
|
4613
|
+
React.useEffect(function () {
|
|
4614
|
+
var targetElement = target && 'current' in target ? target.current : target;
|
|
4615
|
+
setTargetElement(targetElement);
|
|
4616
|
+
}, [target]);
|
|
4617
|
+
React.useEffect(function () {
|
|
4618
|
+
return function () {
|
|
4619
|
+
isolator === null || isolator === void 0 ? void 0 : isolator.deactivate();
|
|
4620
|
+
};
|
|
4621
|
+
}, []);
|
|
4622
|
+
React.useEffect(function () {
|
|
4623
|
+
if (!isolator)
|
|
4624
|
+
return;
|
|
4625
|
+
if (show) {
|
|
4626
|
+
isolator.activate();
|
|
4627
|
+
}
|
|
4628
|
+
else {
|
|
4629
|
+
isolator.deactivate();
|
|
4630
|
+
}
|
|
4631
|
+
return function () {
|
|
4632
|
+
isolator === null || isolator === void 0 ? void 0 : isolator.deactivate();
|
|
4633
|
+
};
|
|
4634
|
+
}, [show, isolator]);
|
|
4635
|
+
React.useEffect(function () {
|
|
4636
|
+
if (popoverRef.current)
|
|
4637
|
+
attachIsolator();
|
|
4638
|
+
}, [popoverRef.current]);
|
|
4639
|
+
React.useEffect(function () {
|
|
4640
|
+
if (show && popoverRef.current) {
|
|
4641
|
+
// Find the first focusable element inside the container
|
|
4642
|
+
var firstFocusableElement = popoverRef.current.querySelector(focusableSelector);
|
|
4643
|
+
if (firstFocusableElement instanceof HTMLElement) {
|
|
4644
|
+
firstFocusableElement.focus();
|
|
4645
|
+
}
|
|
4646
|
+
}
|
|
4647
|
+
targetElement === null || targetElement === void 0 ? void 0 : targetElement.setAttribute('aria-expanded', Boolean(show).toString());
|
|
4648
|
+
}, [show, popoverRef.current]);
|
|
4649
|
+
React.useEffect(function () {
|
|
4650
|
+
var handleEscape = function (event) {
|
|
4651
|
+
if (event.key === 'Escape' ||
|
|
4652
|
+
event.key === 'Esc' ||
|
|
4653
|
+
event.keyCode === 27) {
|
|
4654
|
+
handleClosePopover();
|
|
4655
|
+
}
|
|
4656
|
+
};
|
|
4657
|
+
if (show) {
|
|
4658
|
+
document.body.addEventListener('keyup', handleEscape);
|
|
4659
|
+
}
|
|
4660
|
+
else {
|
|
4661
|
+
document.body.removeEventListener('keyup', handleEscape);
|
|
4662
|
+
}
|
|
4663
|
+
return function () {
|
|
4664
|
+
document.body.removeEventListener('keyup', handleEscape);
|
|
4665
|
+
};
|
|
4666
|
+
}, [show]);
|
|
4667
|
+
React.useEffect(function () {
|
|
4668
|
+
var attrText = targetElement === null || targetElement === void 0 ? void 0 : targetElement.getAttribute('aria-controls');
|
|
4669
|
+
var hasPopupAttr = targetElement === null || targetElement === void 0 ? void 0 : targetElement.getAttribute('aria-haspopup');
|
|
4670
|
+
if (!(attrText === null || attrText === void 0 ? void 0 : attrText.includes(id)) && show) {
|
|
4671
|
+
targetElement === null || targetElement === void 0 ? void 0 : targetElement.setAttribute('aria-controls', id);
|
|
4672
|
+
}
|
|
4673
|
+
if (!hasPopupAttr) {
|
|
4674
|
+
targetElement === null || targetElement === void 0 ? void 0 : targetElement.setAttribute('aria-haspopup', 'true');
|
|
4675
|
+
}
|
|
4676
|
+
}, [targetElement, id, show]);
|
|
4677
|
+
var handleClickOutside = function () {
|
|
4678
|
+
if (show) {
|
|
4679
|
+
handleClosePopover();
|
|
4680
|
+
}
|
|
4681
|
+
};
|
|
4682
|
+
var attachIsolator = function () {
|
|
4683
|
+
if (popoverRef === null || popoverRef === void 0 ? void 0 : popoverRef.current) {
|
|
4684
|
+
setIsolator(new AriaIsolate(popoverRef === null || popoverRef === void 0 ? void 0 : popoverRef.current));
|
|
4685
|
+
}
|
|
4686
|
+
};
|
|
4687
|
+
var handleClosePopover = function () {
|
|
4688
|
+
isolator === null || isolator === void 0 ? void 0 : isolator.deactivate();
|
|
4689
|
+
if (show) {
|
|
4690
|
+
onClose();
|
|
4691
|
+
}
|
|
4692
|
+
};
|
|
4693
|
+
if (!show || !isBrowser())
|
|
4694
|
+
return null;
|
|
4695
|
+
return reactDom.createPortal(React__default["default"].createElement(FocusTrap__default["default"], { focusTrapOptions: {
|
|
4696
|
+
allowOutsideClick: true,
|
|
4697
|
+
fallbackFocus: '.Popover__borderLeft'
|
|
4698
|
+
} },
|
|
4699
|
+
React__default["default"].createElement(ClickOutsideListener, { onClickOutside: handleClickOutside },
|
|
4700
|
+
React__default["default"].createElement("div", tslib.__assign({ id: id, className: classNames__default["default"]('Popover', "Popover--".concat(placement), className, {
|
|
4701
|
+
'Popover--hidden': !show,
|
|
4702
|
+
'Popover--prompt': variant === 'prompt'
|
|
4703
|
+
}), ref: popoverRef, role: "dialog", style: styles.popper }, attributes.popper, props, additionalProps),
|
|
4704
|
+
React__default["default"].createElement("div", { className: "Popover__popoverArrow", ref: setArrowElement, style: styles.arrow }),
|
|
4705
|
+
React__default["default"].createElement("div", { className: "Popover__borderLeft" }),
|
|
4706
|
+
variant === 'prompt' ? (React__default["default"].createElement(PromptPopoverContent, { applyButtonText: applyButtonText, onApply: onApply, closeButtonText: closeButtonText, infoText: infoText || '', onClose: handleClosePopover, infoTextId: "".concat(id, "-label") })) : (children)))), (portal && 'current' in portal ? portal.current : portal) || document.body);
|
|
4707
|
+
});
|
|
4708
|
+
Popover.displayName = 'Popover';
|
|
4709
|
+
|
|
3946
4710
|
var LIGHT_THEME_CLASS = 'cauldron--theme-light';
|
|
3947
4711
|
var DARK_THEME_CLASS = 'cauldron--theme-dark';
|
|
3948
4712
|
var ThemeContext = React.createContext({
|
|
@@ -4033,6 +4797,9 @@ exports.ColumnHeader = ColumnHeader;
|
|
|
4033
4797
|
exports.ColumnLeft = ColumnLeft;
|
|
4034
4798
|
exports.ColumnList = ColumnList;
|
|
4035
4799
|
exports.ColumnRight = ColumnRight;
|
|
4800
|
+
exports.Combobox = Combobox;
|
|
4801
|
+
exports.ComboboxGroup = ComboboxGroup;
|
|
4802
|
+
exports.ComboboxOption = ComboboxOption;
|
|
4036
4803
|
exports.DescriptionDetails = DescriptionDetails;
|
|
4037
4804
|
exports.DescriptionList = DescriptionList;
|
|
4038
4805
|
exports.DescriptionListItem = DescriptionListItem;
|
|
@@ -4048,6 +4815,9 @@ exports.IssuePanel = IssuePanel;
|
|
|
4048
4815
|
exports.Layout = Layout;
|
|
4049
4816
|
exports.Line = Line;
|
|
4050
4817
|
exports.Link = Link;
|
|
4818
|
+
exports.Listbox = Listbox;
|
|
4819
|
+
exports.ListboxGroup = ListboxGroup;
|
|
4820
|
+
exports.ListboxOption = ListboxOption;
|
|
4051
4821
|
exports.Loader = Loader;
|
|
4052
4822
|
exports.LoaderOverlay = LoaderOverlay;
|
|
4053
4823
|
exports.Main = Main;
|
|
@@ -4071,6 +4841,7 @@ exports.PanelContent = PanelContent;
|
|
|
4071
4841
|
exports.PanelHeader = PanelHeader;
|
|
4072
4842
|
exports.PanelTrigger = PanelTrigger$1;
|
|
4073
4843
|
exports.Pointout = Pointout;
|
|
4844
|
+
exports.Popover = Popover;
|
|
4074
4845
|
exports.ProgressBar = ProgressBar;
|
|
4075
4846
|
exports.RadioCardGroup = RadioCardGroup;
|
|
4076
4847
|
exports.RadioGroup = RadioGroup;
|
|
@@ -4093,6 +4864,7 @@ exports.TableHeader = TableHeader;
|
|
|
4093
4864
|
exports.TableRow = TableRow;
|
|
4094
4865
|
exports.Tabs = Tabs;
|
|
4095
4866
|
exports.Tag = Tag;
|
|
4867
|
+
exports.TagButton = TagButton;
|
|
4096
4868
|
exports.TagLabel = TagLabel;
|
|
4097
4869
|
exports.TextField = TextField;
|
|
4098
4870
|
exports.ThemeContext = ThemeContext;
|