@clayui/drop-down
Version:
ClayDropDown component
263 lines (262 loc) • 9.21 kB
JavaScript
;
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var DropDown_exports = {};
__export(DropDown_exports, {
default: () => DropDown_default
});
module.exports = __toCommonJS(DropDown_exports);
var import_core = require("@clayui/core");
var import_icon = __toESM(require("@clayui/icon"));
var import_shared = require("@clayui/shared");
var import_classnames = __toESM(require("classnames"));
var import_react = __toESM(require("react"));
var import_Action = __toESM(require("./Action"));
var import_Caption = __toESM(require("./Caption"));
var import_Divider = __toESM(require("./Divider"));
var import_DropDownContext = require("./DropDownContext");
var import_FocusMenu = require("./FocusMenu");
var import_Group = __toESM(require("./Group"));
var import_Help = __toESM(require("./Help"));
var import_Item = __toESM(require("./Item"));
var import_ItemList = __toESM(require("./ItemList"));
var import_Menu = __toESM(require("./Menu"));
var import_Search = __toESM(require("./Search"));
var import_Section = __toESM(require("./Section"));
const { Collection } = import_core.__NOT_PUBLIC_COLLECTION;
const List = import_react.default.forwardRef(function List2({ children, ...otherProps }, ref) {
return /* @__PURE__ */ import_react.default.createElement("ul", { ...otherProps, className: "list-unstyled", ref }, children);
});
let counter = 0;
function DropDown({
active,
alignmentByViewport,
alignmentPosition,
children,
className,
closeOnClick = false,
closeOnClickOutside,
containerElement: ContainerElement = "div",
defaultActive = false,
filterKey,
hasLeftSymbols,
hasRightSymbols,
items,
menuElementAttrs,
menuHeight,
menuWidth,
offsetFn,
onActiveChange,
renderMenuOnClick = false,
role = "menu",
trigger,
triggerIcon = null,
...otherProps
}) {
const triggerElementRef = (0, import_react.useRef)(null);
const menuElementRef = (0, import_react.useRef)(null);
const [initialized, setInitialized] = (0, import_react.useState)(!renderMenuOnClick);
const [internalActive, setInternalActive] = (0, import_shared.useControlledState)({
defaultName: "defaultActive",
defaultValue: defaultActive,
handleName: "onActiveChange",
name: "active",
onChange: onActiveChange,
value: active
});
const [search, setSearch] = (0, import_react.useState)("");
const ariaControls = (0, import_react.useMemo)(() => {
counter++;
return `clay-dropdown-menu-${counter}`;
}, []);
const openMenu = (0, import_react.useCallback)(
(value) => {
if (!initialized) {
setInitialized(true);
}
setInternalActive(value);
},
[initialized]
);
const { navigationProps } = (0, import_shared.useNavigation)({
activation: "manual",
containerRef: menuElementRef,
loop: true,
orientation: "vertical",
typeahead: true,
visible: internalActive
});
return /* @__PURE__ */ import_react.default.createElement(
ContainerElement,
{
...otherProps,
className: (0, import_classnames.default)("dropdown", className)
},
import_react.default.cloneElement(trigger, {
"aria-controls": internalActive ? ariaControls : void 0,
"aria-expanded": internalActive,
"aria-haspopup": "true",
"children": import_react.default.isValidElement(trigger) && // @ts-ignore
trigger?.type.displayName === "ClayButton" && triggerIcon ? /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, trigger.props.children, " ", /* @__PURE__ */ import_react.default.createElement(import_icon.default, { className: "ml-1", symbol: triggerIcon })) : trigger.props.children,
"className": (0, import_classnames.default)(
"dropdown-toggle",
trigger.props.className
),
"onClick": (event) => {
if (trigger.props.onClick) {
trigger.props.onClick(event);
}
openMenu(!internalActive);
},
"onKeyDown": (event) => {
if (trigger.props.onKeyDown) {
trigger.props.onKeyDown(event);
}
if (event.key === import_shared.Keys.Spacebar) {
openMenu(!internalActive);
}
if (event.key === import_shared.Keys.Down) {
event.preventDefault();
event.stopPropagation();
openMenu(true);
}
if (internalActive && event.key === import_shared.Keys.Down) {
event.preventDefault();
event.stopPropagation();
const list = (0, import_shared.getFocusableList)(menuElementRef);
if (list.length) {
list[0].focus();
}
}
if ([import_shared.Keys.Spacebar, import_shared.Keys.Down].includes(event.key)) {
event.preventDefault();
}
},
"ref": (node) => {
triggerElementRef.current = node;
const { ref } = trigger;
if (typeof ref === "function") {
ref(node);
}
}
}),
initialized && /* @__PURE__ */ import_react.default.createElement(
import_Menu.default,
{
...menuElementAttrs,
active: internalActive,
alignElementRef: triggerElementRef,
alignmentByViewport,
alignmentPosition,
closeOnClickOutside,
hasLeftSymbols,
hasRightSymbols,
height: menuHeight,
id: ariaControls,
offsetFn,
onActiveChange: setInternalActive,
onKeyDown: (event) => {
if (menuElementAttrs?.onKeyDown) {
menuElementAttrs.onKeyDown(event);
}
if (event.key === import_shared.Keys.Tab) {
event.preventDefault();
openMenu(false);
const list = Array.from(
document.querySelectorAll(
import_shared.FOCUSABLE_ELEMENTS.join(",")
)
);
const position = list.indexOf(
triggerElementRef.current
);
const nextElement = list[position + 1];
if (nextElement) {
nextElement.focus();
}
}
navigationProps.onKeyDown(event);
},
ref: menuElementRef,
suppress: [triggerElementRef, menuElementRef],
triggerRef: triggerElementRef,
width: menuWidth
},
/* @__PURE__ */ import_react.default.createElement(
import_FocusMenu.FocusMenu,
{
condition: internalActive,
onRender: () => {
setTimeout(() => {
const list = (0, import_shared.getFocusableList)(menuElementRef);
if (list.length) {
list[0].focus();
}
}, 10);
}
},
/* @__PURE__ */ import_react.default.createElement(
import_DropDownContext.DropDownContext.Provider,
{
value: {
close: () => {
setInternalActive(false);
triggerElementRef.current?.focus();
},
closeOnClick,
filterKey,
onSearch: setSearch,
search,
tabFocus: false
}
},
children instanceof Function ? /* @__PURE__ */ import_react.default.createElement(
Collection,
{
as: List,
items,
role
},
children
) : children
)
)
)
);
}
DropDown.Action = import_Action.default;
DropDown.Caption = import_Caption.default;
DropDown.Divider = import_Divider.default;
DropDown.Group = import_Group.default;
DropDown.Help = import_Help.default;
DropDown.Menu = import_Menu.default;
DropDown.Item = import_Item.default;
DropDown.ItemList = import_ItemList.default;
DropDown.Search = import_Search.default;
DropDown.Section = import_Section.default;
var DropDown_default = DropDown;