UNPKG

react-lightning-design-system

Version:

Salesforce Lightning Design System components built with React

1,087 lines (1,056 loc) 42.6 kB
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray"; import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties"; import _extends from "@babel/runtime/helpers/extends"; import _slicedToArray from "@babel/runtime/helpers/slicedToArray"; var _excluded = ["searchText", "disabled", "opened", "focusedValue", "iconAlign", "comboboxId", "listboxId", "optionIdPrefix", "inputRef", "onInputClick", "onInputChange", "onInputFocus", "onInputBlur", "onInputKeyDown", "onSearchIconClick"], _excluded2 = ["id", "value", "defaultValue", "selected", "defaultSelected", "opened", "defaultOpened", "searchText", "defaultSearchText", "cols", "label", "required", "error", "className", "disabled", "loading", "lookupFilter", "listHeader", "listFooter", "data", "tooltip", "tooltipIcon", "scopes", "targetScope", "defaultTargetScope", "onScopeMenuClick", "onScopeSelect", "iconAlign", "onSelect", "onSearchTextChange", "onLookupRequest", "onBlur", "onFocus", "onValueChange", "onComplete", "elementRef", "inputRef", "dropdownRef"]; import React, { useRef, useContext, useState, useEffect, useId, useMemo, useCallback } from 'react'; import classnames from 'classnames'; import { AutoAlign } from './AutoAlign'; import { Button } from './Button'; import { FormElement } from './FormElement'; import { Icon } from './Icon'; import { Spinner } from './Spinner'; import { isElInChildren, registerStyle } from './util'; import { ComponentSettingsContext } from './ComponentSettings'; import { useControlledValue, useEventCallback, useMergeRefs } from './hooks'; import { createFC } from './common'; /** * */ /** * */ /** * Key handler configuration for keyboard navigation */ /** * Custom hook for keyboard event handling in lookup components */ var useKeyHandler = function useKeyHandler(config) { return useEventCallback(function (e) { var opened = config.opened, onOpen = config.onOpen, onClose = config.onClose, onNavigateDown = config.onNavigateDown, onNavigateUp = config.onNavigateUp, onSelect = config.onSelect, isTabNavigationIgnored = config.isTabNavigationIgnored, onTabNavigation = config.onTabNavigation; switch (e.keyCode) { case 40: // ArrowDown e.preventDefault(); e.stopPropagation(); if (!opened) { onOpen(); } else { onNavigateDown(); } break; case 38: // ArrowUp e.preventDefault(); e.stopPropagation(); if (opened) { onNavigateUp(); } break; case 13: // Enter e.preventDefault(); e.stopPropagation(); onSelect(); break; case 27: // Escape e.preventDefault(); e.stopPropagation(); if (opened) { onClose(); } break; case 9: // Tab if (!isTabNavigationIgnored(e.shiftKey ? 'backward' : 'forward')) { e.preventDefault(); e.stopPropagation(); onTabNavigation(e.shiftKey ? 'backward' : 'forward'); } else { onClose(); } break; } }); }; /** * Props for LookupSelectedState component */ /** * Component for displaying selected state */ var LookupSelectedState = function LookupSelectedState(_ref) { var selected = _ref.selected, disabled = _ref.disabled, listboxId = _ref.listboxId, onRemoveSelection = _ref.onRemoveSelection; var formElementClassnames = classnames('slds-combobox__form-element', 'slds-input-has-icon', "slds-input-has-icon_".concat(selected.icon ? 'left-' : '', "right")); return /*#__PURE__*/React.createElement("div", { className: "slds-combobox slds-dropdown-trigger slds-dropdown-trigger_click" }, /*#__PURE__*/React.createElement("div", { className: formElementClassnames, role: "none" }, selected.icon && /*#__PURE__*/React.createElement(Icon, { containerClassName: "slds-combobox__input-entity-icon", category: selected.category, icon: selected.icon, size: "small" }), /*#__PURE__*/React.createElement("button", { type: "button", role: "combobox", tabIndex: disabled ? -1 : 0, className: "slds-input_faux slds-combobox__input slds-combobox__input-value", "aria-controls": listboxId, "aria-haspopup": "listbox", "aria-expanded": "false" }, /*#__PURE__*/React.createElement("span", { className: "slds-truncate" }, selected.label)), /*#__PURE__*/React.createElement(Button, { type: "icon", icon: "close", className: "slds-input__icon slds-input__icon_right", title: "Remove selected option", onClick: onRemoveSelection }, /*#__PURE__*/React.createElement("span", { className: "slds-assistive-text" }, "Remove selected option")))); }; /** * Props for LookupScopeSelectorContainer component */ /** * Container component for scope selector dropdown with AutoAlign */ var LookupScopeSelectorContainer = function LookupScopeSelectorContainer(_ref2) { var scopeListboxId = _ref2.scopeListboxId, dropdownRef = _ref2.dropdownRef, children = _ref2.children, alignment = _ref2.alignment, autoAlignContentRef = _ref2.autoAlignContentRef; var _alignment = _slicedToArray(alignment, 2), vertAlign = _alignment[0], align = _alignment[1]; var dropdownClassNames = classnames('slds-dropdown', vertAlign ? "slds-dropdown_".concat(vertAlign) : undefined, align ? "slds-dropdown_".concat(align) : undefined, 'slds-dropdown_length-with-icon-7', 'slds-dropdown_fluid'); return /*#__PURE__*/React.createElement("div", { id: scopeListboxId, className: dropdownClassNames, role: "listbox", "aria-label": "Scope Options", ref: useMergeRefs([dropdownRef, autoAlignContentRef]) }, children); }; /** * Props for LookupScopeSelector component */ /** * Component for scope selector in multi-entity lookup */ var LookupScopeSelector = function LookupScopeSelector(_ref3) { var _scopes$find; var portalClassName = _ref3.portalClassName, scopes = _ref3.scopes, targetScope = _ref3.targetScope, disabled = _ref3.disabled, scopeListboxId = _ref3.scopeListboxId, getScopeOptionId = _ref3.getScopeOptionId, onScopeMenuClick_ = _ref3.onScopeMenuClick, onScopeSelect_ = _ref3.onScopeSelect; var dropdownRef = useRef(null); var _useState = useState(false), _useState2 = _slicedToArray(_useState, 2), scopeOpened = _useState2[0], setScopeOpened = _useState2[1]; var _useState3 = useState(-1), _useState4 = _slicedToArray(_useState3, 2), scopeFocusedIndex = _useState4[0], setScopeFocusedIndex = _useState4[1]; var currentScope = (_scopes$find = scopes.find(function (scope) { return scope.value === targetScope; })) !== null && _scopes$find !== void 0 ? _scopes$find : scopes[0]; // Scroll focused scope element into view var scrollFocusedScopeIntoView = useEventCallback(function (nextFocusedIndex) { if (nextFocusedIndex < 0 || !scopes) { return; } var scopeDropdown = document.getElementById(scopeListboxId); if (!scopeDropdown) { return; } var targetElement = scopeDropdown.querySelector("#".concat(CSS.escape(getScopeOptionId(nextFocusedIndex)))); if (!(targetElement instanceof HTMLElement)) { return; } targetElement.focus(); }); var onScopeSelect = useEventCallback(function (scope) { setScopeOpened(false); onScopeSelect_ === null || onScopeSelect_ === void 0 || onScopeSelect_(scope); }); var onScopeMenuClick = useEventCallback(function () { setScopeOpened(!scopeOpened); onScopeMenuClick_ === null || onScopeMenuClick_ === void 0 || onScopeMenuClick_(); }); var onScopeKeyDown = useKeyHandler({ type: 'scope', opened: scopeOpened, onOpen: function onOpen() { if (!scopes) return; setScopeOpened(true); setScopeFocusedIndex(0); }, onClose: function onClose() { setScopeOpened(false); setScopeFocusedIndex(-1); }, onNavigateDown: function onNavigateDown() { if (!scopes) return; var nextIndex = Math.min(scopeFocusedIndex + 1, scopes.length - 1); setScopeFocusedIndex(nextIndex); scrollFocusedScopeIntoView(nextIndex); }, onNavigateUp: function onNavigateUp() { if (!scopes) return; var prevIndex = Math.max(scopeFocusedIndex - 1, 0); setScopeFocusedIndex(prevIndex); scrollFocusedScopeIntoView(prevIndex); }, onSelect: function onSelect() { if (!scopes) return; if (scopeOpened && scopeFocusedIndex >= 0) { var selectedScope = scopes[scopeFocusedIndex]; if (selectedScope) { onScopeSelect(selectedScope.value); setScopeOpened(false); setScopeFocusedIndex(-1); } } else { setScopeOpened(!scopeOpened); } }, isTabNavigationIgnored: function isTabNavigationIgnored(direction) { if (!scopes) { return false; } return scopeFocusedIndex === -1 || direction === 'backward' && scopeFocusedIndex <= 0 || direction === 'forward' && scopeFocusedIndex >= scopes.length - 1; }, onTabNavigation: function onTabNavigation(direction) { if (!scopes) return; if (direction === 'backward') { if (scopeFocusedIndex <= 0) { setScopeOpened(false); setScopeFocusedIndex(-1); } else { var prevIndex = Math.max(scopeFocusedIndex - 1, 0); setScopeFocusedIndex(prevIndex); scrollFocusedScopeIntoView(prevIndex); } } else { if (scopeFocusedIndex >= scopes.length - 1) { setScopeOpened(false); setScopeFocusedIndex(-1); } else { var nextIndex = Math.min(scopeFocusedIndex + 1, scopes.length - 1); setScopeFocusedIndex(nextIndex); scrollFocusedScopeIntoView(nextIndex); } } } }); var onScopeBlur = useEventCallback(function (e) { if (e.relatedTarget !== null) { if (!scopes) { return; } var prevIndex = Math.max(scopeFocusedIndex - 1, 0); var nextIndex = Math.min(scopeFocusedIndex + 1, scopes.length - 1); if (e.relatedTarget.id === getScopeOptionId(prevIndex) || e.relatedTarget.id === getScopeOptionId(nextIndex)) { // catch keyborad event return; } } setTimeout(function () { if (!isFocusedInComponent()) { setScopeOpened(false); } }, 10); }); var _useContext = useContext(ComponentSettingsContext), getActiveElement = _useContext.getActiveElement; var isFocusedInComponent = useEventCallback(function () { var targetEl = getActiveElement(); return isElInChildren(dropdownRef.current, targetEl); }); return /*#__PURE__*/React.createElement("div", { className: "react-slds-lookup-scope-selector slds-combobox_object-switcher slds-combobox-addon_start" }, /*#__PURE__*/React.createElement("div", { className: "slds-form-element" }, /*#__PURE__*/React.createElement("label", { className: "slds-form-element__label slds-assistive-text" }, "Filter Search by:"), /*#__PURE__*/React.createElement("div", { className: "slds-form-element__control" }, /*#__PURE__*/React.createElement("div", { className: "react-slds-lookup-scope-combobox-container slds-combobox_container slds-has-icon-only" }, /*#__PURE__*/React.createElement("div", { className: classnames('slds-combobox slds-dropdown-trigger slds-dropdown-trigger_click', { 'slds-is-open': scopeOpened }) }, /*#__PURE__*/React.createElement("div", { className: "slds-combobox__form-element slds-input-has-icon slds-input-has-icon_left-right", role: "none" }, /*#__PURE__*/React.createElement(Icon, { containerClassName: "react-slds-lookup-current-scope-icon-container slds-is-absolute", className: "react-slds-lookup-current-scope-icon", category: currentScope.category, icon: currentScope.icon, size: "small" }), /*#__PURE__*/React.createElement("input", { type: "text", className: "react-slds-lookup-scope-input slds-input slds-combobox__input slds-combobox__input-value", "aria-controls": "objectswitcher-listbox-id", "aria-expanded": scopeOpened, "aria-haspopup": "listbox", autoComplete: "off", role: "combobox", placeholder: " ", value: targetScope || '', disabled: disabled, onClick: onScopeMenuClick, onBlur: onScopeBlur, onKeyDown: onScopeKeyDown, readOnly: true }), /*#__PURE__*/React.createElement(Icon, { containerClassName: "react-slds-lookup-scope-down-icon-container slds-is-absolute", className: "react-slds-lookup-scope-down-icon", icon: "down", size: "x-small" })), scopeOpened && /*#__PURE__*/React.createElement(AutoAlign, { triggerSelector: ".react-slds-lookup-scope-selector", alignmentStyle: "menu", portalClassName: portalClassName }, function (injectedProps) { return /*#__PURE__*/React.createElement(LookupScopeSelectorContainer, _extends({ scopeListboxId: scopeListboxId, dropdownRef: dropdownRef }, injectedProps), /*#__PURE__*/React.createElement("ul", { className: "slds-listbox slds-listbox_vertical", role: "presentation", onBlur: onScopeBlur, onKeyDown: onScopeKeyDown }, scopes.map(function (scope, index) { return /*#__PURE__*/React.createElement("li", { key: scope.value, role: "presentation", className: "slds-listbox__item" }, /*#__PURE__*/React.createElement("div", { id: getScopeOptionId(index), className: classnames('slds-media slds-media_center slds-listbox__option slds-listbox__option_entity', { 'slds-has-focus': scopeFocusedIndex === index }), role: "option", "aria-selected": scope.value === targetScope, tabIndex: 0, onClick: function onClick() { return onScopeSelect(scope.value); } }, /*#__PURE__*/React.createElement("span", { className: "slds-media__figure slds-listbox__option-icon" }, scope.icon && /*#__PURE__*/React.createElement(Icon, { category: scope.category, icon: scope.icon, size: "small" })), /*#__PURE__*/React.createElement("span", { className: "slds-media__body" }, /*#__PURE__*/React.createElement("span", { className: "slds-listbox__option-text slds-listbox__option-text_entity" }, scope.label)))); }))); })))))); }; var SCOPE_INPUT_ZINDEX = 1; /** * Props for LookupSearchInput component */ /** * Component for search input */ var LookupSearchInput = function LookupSearchInput(_ref4) { var searchText = _ref4.searchText, disabled = _ref4.disabled, opened = _ref4.opened, focusedValue = _ref4.focusedValue, iconAlign = _ref4.iconAlign, comboboxId = _ref4.comboboxId, listboxId = _ref4.listboxId, optionIdPrefix = _ref4.optionIdPrefix, inputRef = _ref4.inputRef, onInputClick = _ref4.onInputClick, onInputChange = _ref4.onInputChange, onInputFocus = _ref4.onInputFocus, onInputBlur = _ref4.onInputBlur, onInputKeyDown = _ref4.onInputKeyDown, onSearchIconClick = _ref4.onSearchIconClick, rprops = _objectWithoutProperties(_ref4, _excluded); var hasValue = searchText.length > 0; var inputClassNames = classnames('slds-input', 'slds-combobox__input', { 'slds-has-focus': opened, 'slds-combobox__input-value': hasValue }); var inputIconClasses = iconAlign === 'left' ? 'slds-combobox__form-element slds-input-has-icon slds-input-has-icon_left' : 'slds-combobox__form-element slds-input-has-icon slds-input-has-icon_right'; return /*#__PURE__*/React.createElement("div", { className: inputIconClasses, role: "none" }, iconAlign === 'left' && /*#__PURE__*/React.createElement(Button, { type: "icon", icon: "search", disabled: disabled, className: classnames('slds-input__icon', "slds-input__icon_".concat(iconAlign)), tabIndex: -1, onClick: disabled ? undefined : onSearchIconClick }), /*#__PURE__*/React.createElement("input", _extends({}, rprops, { type: "text", className: inputClassNames, id: comboboxId, ref: inputRef, value: searchText, disabled: disabled, "aria-autocomplete": "list", "aria-controls": listboxId, "aria-expanded": opened, "aria-haspopup": "listbox", "aria-activedescendant": focusedValue ? "".concat(optionIdPrefix, "-").concat(focusedValue) : undefined, autoComplete: "off", role: "combobox", onClick: onInputClick, onChange: onInputChange, onFocus: onInputFocus, onBlur: onInputBlur, onKeyDown: onInputKeyDown })), iconAlign === 'right' && /*#__PURE__*/React.createElement(Button, { type: "icon", icon: "search", disabled: disabled, className: classnames('slds-input__icon', "slds-input__icon_".concat(iconAlign)), tabIndex: -1, onClick: disabled ? undefined : onSearchIconClick })); }; /** * Props for LookupOption component */ /** * Component for individual lookup option */ var LookupOption = function LookupOption(_ref5) { var entry = _ref5.entry, isFocused = _ref5.isFocused, getOptionId = _ref5.getOptionId, onOptionClick = _ref5.onOptionClick, onOptionFocus = _ref5.onOptionFocus; var itemClassNames = classnames('slds-media', 'slds-media_center', 'slds-listbox__option', 'slds-listbox__option_entity', { 'slds-listbox__option_has-meta': entry.meta, 'slds-has-focus': isFocused }); return /*#__PURE__*/React.createElement("li", { key: entry.value, role: "presentation", className: "slds-listbox__item" }, /*#__PURE__*/React.createElement("div", { id: getOptionId(entry.value), className: itemClassNames, role: "option", "aria-selected": isFocused, tabIndex: 0, onFocus: function onFocus() { return onOptionFocus(entry.value); }, onClick: function onClick() { return onOptionClick(entry); } }, /*#__PURE__*/React.createElement("span", { className: "slds-media__figure slds-listbox__option-icon" }, entry.icon && /*#__PURE__*/React.createElement(Icon, { category: entry.category, icon: entry.icon, size: "small" })), /*#__PURE__*/React.createElement("span", { className: "slds-media__body" }, /*#__PURE__*/React.createElement("span", { className: "slds-listbox__option-text slds-listbox__option-text_entity" }, entry.label), entry.meta && /*#__PURE__*/React.createElement("span", { className: "slds-listbox__option-meta slds-listbox__option-meta_entity" }, entry.meta)))); }; /** * Props for LookupDropdownContainer component */ /** * Container component for dropdown with merged refs */ var LookupDropdownContainer = function LookupDropdownContainer(_ref6) { var listboxId = _ref6.listboxId, loading = _ref6.loading, dropdownRef = _ref6.dropdownRef, children = _ref6.children, alignment = _ref6.alignment, autoAlignContentRef = _ref6.autoAlignContentRef; var _alignment2 = _slicedToArray(alignment, 2), vertAlign = _alignment2[0], align = _alignment2[1]; var dropdownClassNames = classnames('react-slds-lookup-dropdown-main', 'slds-dropdown', vertAlign ? "slds-dropdown_".concat(vertAlign) : undefined, align ? "slds-dropdown_".concat(align) : undefined, 'slds-dropdown_length-with-icon-7', 'slds-dropdown_fluid', 'slds-scrollable_none'); return /*#__PURE__*/React.createElement("div", { id: listboxId, className: dropdownClassNames, role: "listbox", "aria-label": "Search Results", tabIndex: 0, "aria-busy": loading, ref: useMergeRefs([dropdownRef, autoAlignContentRef]) }, children); }; /** * Props for LookupDropdown component */ /** * Component for dropdown menu */ var LookupDropdown = function LookupDropdown(_ref7) { var portalClassName = _ref7.portalClassName, opened = _ref7.opened, loading = _ref7.loading, listboxId = _ref7.listboxId, dropdownRef = _ref7.dropdownRef, listHeader = _ref7.listHeader, listHeaderIdSeed = _ref7.listHeaderIdSeed, listFooter = _ref7.listFooter, listFooterIdSeed = _ref7.listFooterIdSeed, filteredData = _ref7.filteredData, focusedValue = _ref7.focusedValue, getOptionId = _ref7.getOptionId, onOptionClick = _ref7.onOptionClick, onOptionFocus = _ref7.onOptionFocus, onBlur = _ref7.onBlur, onKeyDown = _ref7.onKeyDown; if (!opened) return null; return /*#__PURE__*/React.createElement(AutoAlign, { triggerSelector: ".react-slds-lookup", alignmentStyle: "menu", portalClassName: portalClassName }, function (injectedProps) { return /*#__PURE__*/React.createElement(LookupDropdownContainer, _extends({ listboxId: listboxId, loading: loading, dropdownRef: dropdownRef }, injectedProps), listHeader ? /*#__PURE__*/React.createElement("ul", { className: "slds-listbox slds-listbox_vertical", role: "presentation", onKeyDown: onKeyDown, onBlur: onBlur }, /*#__PURE__*/React.createElement("li", { role: "presentation", className: "slds-listbox__item" }, /*#__PURE__*/React.createElement("div", { id: getOptionId(listHeaderIdSeed), className: "slds-media slds-media_center slds-listbox__option slds-listbox__option_entity slds-listbox__option_term", role: "option", "aria-selected": "true", tabIndex: 0, onFocus: function onFocus() { return onOptionFocus(listHeaderIdSeed); } }, listHeader))) : null, /*#__PURE__*/React.createElement("ul", { className: "react-slds-lookup-list slds-listbox slds-listbox_vertical slds-scrollable_y", role: "presentation", onKeyDown: onKeyDown, onBlur: onBlur }, filteredData.map(function (entry) { return /*#__PURE__*/React.createElement(LookupOption, { key: entry.value, entry: entry, isFocused: focusedValue === entry.value, getOptionId: getOptionId, onOptionClick: onOptionClick, onOptionFocus: onOptionFocus }); }), loading ? /*#__PURE__*/React.createElement("li", { role: "option", className: "slds-listbox__item" }, /*#__PURE__*/React.createElement("div", { className: "slds-align_absolute-center slds-p-top_medium" }, /*#__PURE__*/React.createElement(Spinner, { container: false, size: "x-small", layout: "inline" }))) : null), listFooter ? /*#__PURE__*/React.createElement("ul", { className: "slds-listbox slds-listbox_vertical", role: "presentation", onKeyDown: onKeyDown, onBlur: onBlur }, /*#__PURE__*/React.createElement("li", { role: "presentation", className: "slds-listbox__item" }, /*#__PURE__*/React.createElement("div", { id: getOptionId(listFooterIdSeed), className: "slds-media slds-media_center slds-listbox__option slds-listbox__option_entity slds-listbox__option_term", role: "option", tabIndex: 0, onFocus: function onFocus() { return onOptionFocus(listFooterIdSeed); } }, listFooter))) : null); }); }; // manually replaces where `max-height` is specified var LIST_PARENT_MAX_HEIGHT = 'unset'; var LIST_CONTENT_MAX_HEIGHT = 'calc((1.5rem + 1rem) * 7)'; // copied from `.slds-dropdown_length-with-icon-7` /** * */ function useInitComponentStyle() { useEffect(function () { registerStyle('lookup-search', [['.react-slds-lookup-current-scope-icon-container', "{ top: 50%; transform: translateY(-50%); left: 14.2%; pointer-events: none; z-index: ".concat(SCOPE_INPUT_ZINDEX + 1, "; }")], ['.react-slds-lookup-scope-input:not(:disabled)', '{ cursor: pointer; }'], ['.react-slds-lookup-scope-input.react-slds-lookup-scope-input.react-slds-lookup-scope-input', "{ padding-left: 1.5rem; z-index: ".concat(SCOPE_INPUT_ZINDEX, "; }")], ['.react-slds-lookup-scope-down-icon-container', "{ line-height: 0; bottom: 17%; right: 15.7%; pointer-events: none; z-index: ".concat(SCOPE_INPUT_ZINDEX + 1, "; }")], ['.react-slds-lookup-scope-down-icon-container .react-slds-lookup-scope-down-icon', '{ width: 0.8rem; height: 0.8rem; }'], ['.react-slds-lookup-dropdown-main', "{ max-height: ".concat(LIST_PARENT_MAX_HEIGHT, "; min-width: 15rem; }")], ['.react-slds-lookup-list', "{ max-height: ".concat(LIST_CONTENT_MAX_HEIGHT, "; }")]]); }, []); } /** * */ /** * */ export var Lookup = createFC(function (props) { var _ref8; var id_ = props.id, value_ = props.value, defaultValue = props.defaultValue, selected_ = props.selected, defaultSelected = props.defaultSelected, opened_ = props.opened, defaultOpened = props.defaultOpened, searchText_ = props.searchText, defaultSearchText = props.defaultSearchText, cols = props.cols, label = props.label, required = props.required, error = props.error, className = props.className, disabled = props.disabled, loading = props.loading, lookupFilter = props.lookupFilter, listHeader = props.listHeader, listFooter = props.listFooter, _props$data = props.data, data = _props$data === void 0 ? [] : _props$data, tooltip = props.tooltip, tooltipIcon = props.tooltipIcon, scopes = props.scopes, targetScope_ = props.targetScope, defaultTargetScope = props.defaultTargetScope, onScopeMenuClick_ = props.onScopeMenuClick, onScopeSelect_ = props.onScopeSelect, _props$iconAlign = props.iconAlign, iconAlign = _props$iconAlign === void 0 ? 'right' : _props$iconAlign, onSelect_ = props.onSelect, onSearchTextChange_ = props.onSearchTextChange, onLookupRequest_ = props.onLookupRequest, onBlur_ = props.onBlur, onFocus_ = props.onFocus, onValueChange = props.onValueChange, onComplete = props.onComplete, elementRef_ = props.elementRef, inputRef_ = props.inputRef, dropdownRef_ = props.dropdownRef, rprops = _objectWithoutProperties(props, _excluded2); useInitComponentStyle(); var fallbackId = useId(); var comboboxId = id_ !== null && id_ !== void 0 ? id_ : "".concat(fallbackId, "-combobox"); var listboxId = "".concat(fallbackId, "-listbox"); var optionIdPrefix = "".concat(comboboxId, "-option"); var getOptionId = function getOptionId(value) { return "".concat(optionIdPrefix, "-").concat(value); }; var scopeListboxId = "".concat(comboboxId, "-scope-listbox"); var getScopeOptionId = function getScopeOptionId(index) { return "".concat(scopeListboxId, "-option-").concat(index); }; var _useControlledValue = useControlledValue(value_, defaultValue !== null && defaultValue !== void 0 ? defaultValue : null), _useControlledValue2 = _slicedToArray(_useControlledValue, 2), value = _useControlledValue2[0], setValue = _useControlledValue2[1]; var _useControlledValue3 = useControlledValue(selected_, (_ref8 = defaultSelected !== null && defaultSelected !== void 0 ? defaultSelected : data === null || data === void 0 ? void 0 : data.find(function (entry) { return entry.value === value; })) !== null && _ref8 !== void 0 ? _ref8 : null), _useControlledValue4 = _slicedToArray(_useControlledValue3, 2), selected = _useControlledValue4[0], setSelected = _useControlledValue4[1]; var _useControlledValue5 = useControlledValue(opened_, defaultOpened !== null && defaultOpened !== void 0 ? defaultOpened : false), _useControlledValue6 = _slicedToArray(_useControlledValue5, 2), opened = _useControlledValue6[0], setOpened = _useControlledValue6[1]; var _useControlledValue7 = useControlledValue(searchText_, defaultSearchText !== null && defaultSearchText !== void 0 ? defaultSearchText : ''), _useControlledValue8 = _slicedToArray(_useControlledValue7, 2), searchText = _useControlledValue8[0], setSearchText = _useControlledValue8[1]; var _useControlledValue9 = useControlledValue(targetScope_, defaultTargetScope !== null && defaultTargetScope !== void 0 ? defaultTargetScope : scopes && scopes.length > 0 ? scopes[0].value : undefined), _useControlledValue10 = _slicedToArray(_useControlledValue9, 2), targetScope = _useControlledValue10[0], setTargetScope = _useControlledValue10[1]; var _useState5 = useState(), _useState6 = _slicedToArray(_useState5, 2), focusedValue = _useState6[0], setFocusedValue = _useState6[1]; var listHeaderIdSeed = useMemo(function () { return [].concat(_toConsumableArray(data.map(function (entry) { return entry.value; })), ['header']).join('-'); }, [data]); var listFooterIdSeed = useMemo(function () { return [].concat(_toConsumableArray(data.map(function (entry) { return entry.value; })), ['footer']).join('-'); }, [data]); // Memoized option values - filtered data with optional header and footer var optionValues = useMemo(function () { var filteredData = lookupFilter ? data.filter(function (entry) { return lookupFilter(entry, searchText, targetScope); }) : data; return [listHeader ? listHeaderIdSeed : undefined].concat(_toConsumableArray(filteredData.map(function (entry) { return entry.value; })), [listFooter ? listFooterIdSeed : undefined]).filter(function (value) { return value !== undefined; }); }, [data, lookupFilter, searchText, targetScope, listHeader, listHeaderIdSeed, listFooter, listFooterIdSeed]); // Get next option value for keyboard navigation var getNextValue = useCallback(function (currentValue) { if (optionValues.length === 0) return undefined; if (!currentValue) return optionValues[0]; var currentIndex = optionValues.indexOf(currentValue); return optionValues[Math.min(currentIndex + 1, optionValues.length - 1)]; // not wrap around }, [optionValues]); // Get previous option value for keyboard navigation var getPrevValue = useCallback(function (currentValue) { if (optionValues.length === 0) return undefined; if (!currentValue) return optionValues[optionValues.length - 1]; var currentIndex = optionValues.indexOf(currentValue); return optionValues[Math.max(currentIndex - 1, 0)]; // not wrap around }, [optionValues]); // Scroll focused element into view var scrollFocusedElementIntoView = useEventCallback(function (nextFocusedValue) { if (!nextFocusedValue || !dropdownElRef.current) { return; } var dropdownContainer = dropdownElRef.current; var targetElement = dropdownContainer.querySelector("#".concat(CSS.escape(getOptionId(nextFocusedValue)))); if (!(targetElement instanceof HTMLElement)) { return; } targetElement.focus(); }); // Set initial focus when dropdown opens useEffect(function () { if (!opened) { setFocusedValue(undefined); } }, [opened, optionValues, focusedValue, scrollFocusedElementIntoView]); var elRef = useRef(null); var elementRef = useMergeRefs([elRef, elementRef_]); var inputElRef = useRef(null); var inputRef = useMergeRefs([inputElRef, inputRef_]); var dropdownElRef = useRef(null); var dropdownRef = useMergeRefs([dropdownElRef, dropdownRef_]); var onScopeMenuClick = useEventCallback(function () { setOpened(false); onScopeMenuClick_ === null || onScopeMenuClick_ === void 0 || onScopeMenuClick_(); }); var _onSelect = useEventCallback(function (selectedEntry) { var _selectedEntry$value; var currValue = (_selectedEntry$value = selectedEntry === null || selectedEntry === void 0 ? void 0 : selectedEntry.value) !== null && _selectedEntry$value !== void 0 ? _selectedEntry$value : null; setValue(currValue); setSelected(selectedEntry); onValueChange === null || onValueChange === void 0 || onValueChange(currValue, value); onSelect_ === null || onSelect_ === void 0 || onSelect_(selectedEntry); }); var onSearchTextChange = useEventCallback(function (newSearchText) { setSearchText(newSearchText); onSearchTextChange_ === null || onSearchTextChange_ === void 0 || onSearchTextChange_(newSearchText); if (newSearchText && !opened) { setOpened(true); onLookupRequest_ === null || onLookupRequest_ === void 0 || onLookupRequest_(newSearchText); } }); var onInputClick = useEventCallback(function () { onFocus_ === null || onFocus_ === void 0 || onFocus_(); }); var onInputChange = useEventCallback(function (e) { var newSearchText = e.target.value; onSearchTextChange(newSearchText); setOpened(true); onLookupRequest_ === null || onLookupRequest_ === void 0 || onLookupRequest_(newSearchText); }); var onInputFocus = useEventCallback(function () { onFocus_ === null || onFocus_ === void 0 || onFocus_(); }); var onInputBlur = useEventCallback(function (e) { if (e.relatedTarget !== null) { var _prevValue = getPrevValue(focusedValue); var nextValue = getNextValue(focusedValue); if (_prevValue && e.relatedTarget.id === getOptionId(_prevValue) || nextValue && e.relatedTarget.id === getOptionId(nextValue)) { // catch keyborad event return; } } setTimeout(function () { if (!isFocusedInComponent()) { setOpened(false); onBlur_ === null || onBlur_ === void 0 || onBlur_(); onComplete === null || onComplete === void 0 || onComplete(true); } }, 10); }); var _useContext2 = useContext(ComponentSettingsContext), getActiveElement = _useContext2.getActiveElement; var isFocusedInComponent = useEventCallback(function () { var targetEl = getActiveElement(); return isElInChildren(containerRef.current, targetEl) || isElInChildren(dropdownElRef.current, targetEl); }); var onInputKeyDown = useKeyHandler({ type: 'search', opened: opened, onOpen: function onOpen() { setOpened(true); onLookupRequest_ === null || onLookupRequest_ === void 0 || onLookupRequest_(searchText); }, onClose: function onClose() { setOpened(false); onComplete === null || onComplete === void 0 || onComplete(true); }, onNavigateDown: function onNavigateDown() { var nextValue = getNextValue(focusedValue); setFocusedValue(nextValue); scrollFocusedElementIntoView(nextValue); }, onNavigateUp: function onNavigateUp() { var prevValue = getPrevValue(focusedValue); setFocusedValue(prevValue); scrollFocusedElementIntoView(prevValue); }, onSelect: function onSelect() { if (opened && focusedValue) { var selectedEntry = data.find(function (entry) { return entry.value === focusedValue; }); if (selectedEntry) { _onSelect(selectedEntry); setOpened(false); onComplete === null || onComplete === void 0 || onComplete(); } } else if (searchText) { setOpened(true); onLookupRequest_ === null || onLookupRequest_ === void 0 || onLookupRequest_(searchText); } }, isTabNavigationIgnored: function isTabNavigationIgnored(direction) { var currentIndex = focusedValue ? optionValues.indexOf(focusedValue) : -1; return currentIndex === -1 || direction === 'backward' && currentIndex <= 0 || direction === 'forward' && currentIndex >= optionValues.length - 1; }, onTabNavigation: function onTabNavigation(direction) { var currentIndex = focusedValue ? optionValues.indexOf(focusedValue) : -1; if (direction === 'backward') { if (currentIndex <= 0) { setOpened(false); onComplete === null || onComplete === void 0 || onComplete(); } else { var _prevValue2 = getPrevValue(focusedValue); setFocusedValue(_prevValue2); scrollFocusedElementIntoView(_prevValue2); } } else { if (currentIndex >= optionValues.length - 1) { setOpened(false); onComplete === null || onComplete === void 0 || onComplete(); } else { var nextValue = getNextValue(focusedValue); setFocusedValue(nextValue); scrollFocusedElementIntoView(nextValue); } } } }); var onOptionClick = useEventCallback(function (entry) { _onSelect(entry); setOpened(false); setTimeout(function () { var _inputElRef$current; (_inputElRef$current = inputElRef.current) === null || _inputElRef$current === void 0 || _inputElRef$current.focus(); onComplete === null || onComplete === void 0 || onComplete(); }, 10); }); var onOptionFocus = useEventCallback(function (value) { setFocusedValue(value); }); var onSearchIconClick = useEventCallback(function () { var _inputElRef$current2; (_inputElRef$current2 = inputElRef.current) === null || _inputElRef$current2 === void 0 || _inputElRef$current2.focus(); setOpened(true); onLookupRequest_ === null || onLookupRequest_ === void 0 || onLookupRequest_(searchText); }); var onRemoveSelection = useEventCallback(function () { _onSelect(null); setSearchText(''); setOpened(true); onLookupRequest_ === null || onLookupRequest_ === void 0 || onLookupRequest_(''); setTimeout(function () { var _inputElRef$current3; (_inputElRef$current3 = inputElRef.current) === null || _inputElRef$current3 === void 0 || _inputElRef$current3.focus(); }, 10); }); var hasSelection = selected != null; var containerRef = useRef(null); var containerClassNames = classnames('react-slds-lookup', "react-slds-lookup-scope-".concat(scopes ? 'multi' : 'single'), 'slds-combobox_container', { 'slds-has-selection': hasSelection }, className); var comboboxClassNames = classnames('slds-combobox', 'slds-dropdown-trigger', 'slds-dropdown-trigger_click', { 'slds-is-open': opened }); var formElemProps = { controlId: comboboxId, label: label, required: required, error: error, cols: cols, tooltip: tooltip, tooltipIcon: tooltipIcon, elementRef: elementRef }; var filteredData = lookupFilter ? data.filter(function (entry) { return lookupFilter(entry, searchText, targetScope); }) : data; // Render selected state if (hasSelection && selected) { return /*#__PURE__*/React.createElement(FormElement, formElemProps, /*#__PURE__*/React.createElement("div", { ref: containerRef, className: containerClassNames }, /*#__PURE__*/React.createElement(LookupSelectedState, { selected: selected, disabled: disabled, listboxId: listboxId, onRemoveSelection: onRemoveSelection }))); } // Render search state with optional scope selector if (scopes && scopes.length > 0) { // Multi Entity Lookup with scope selector return /*#__PURE__*/React.createElement(FormElement, formElemProps, /*#__PURE__*/React.createElement("div", { ref: containerRef, className: containerClassNames }, /*#__PURE__*/React.createElement("div", { className: "react-slds-combobox-group slds-combobox-group" }, /*#__PURE__*/React.createElement(LookupScopeSelector, { portalClassName: containerClassNames, scopes: scopes, targetScope: targetScope, disabled: disabled, scopeListboxId: scopeListboxId, getScopeOptionId: getScopeOptionId, onScopeMenuClick: onScopeMenuClick, onScopeSelect: function onScopeSelect(scope) { setTargetScope(scope); onScopeSelect_ === null || onScopeSelect_ === void 0 || onScopeSelect_(scope); } }), /*#__PURE__*/React.createElement("div", { className: "slds-combobox_container slds-combobox-addon_end" }, /*#__PURE__*/React.createElement("div", { className: comboboxClassNames, ref: elementRef }, /*#__PURE__*/React.createElement(LookupSearchInput, _extends({}, rprops, { searchText: searchText, disabled: disabled, opened: opened, focusedValue: focusedValue, iconAlign: iconAlign, comboboxId: comboboxId, listboxId: listboxId, optionIdPrefix: optionIdPrefix, inputRef: inputRef, onInputClick: onInputClick, onInputChange: onInputChange, onInputFocus: onInputFocus, onInputBlur: onInputBlur, onInputKeyDown: onInputKeyDown, onSearchIconClick: onSearchIconClick }))))), /*#__PURE__*/React.createElement("div", { className: "slds-combobox_container" }, /*#__PURE__*/React.createElement("div", { className: comboboxClassNames }, /*#__PURE__*/React.createElement(LookupDropdown, { portalClassName: containerClassNames, opened: opened, loading: loading, listboxId: listboxId, dropdownRef: dropdownRef, listHeader: listHeader, listHeaderIdSeed: listHeaderIdSeed, listFooter: listFooter, listFooterIdSeed: listFooterIdSeed, filteredData: filteredData, focusedValue: focusedValue, getOptionId: getOptionId, onOptionClick: onOptionClick, onOptionFocus: onOptionFocus, onBlur: onInputBlur, onKeyDown: onInputKeyDown }))))); } // Render simple search state (no scopes) return /*#__PURE__*/React.createElement(FormElement, formElemProps, /*#__PURE__*/React.createElement("div", { ref: containerRef, className: containerClassNames }, /*#__PURE__*/React.createElement("div", { className: comboboxClassNames, ref: elementRef }, /*#__PURE__*/React.createElement(LookupSearchInput, _extends({}, rprops, { searchText: searchText, disabled: disabled, opened: opened, focusedValue: focusedValue, iconAlign: iconAlign, comboboxId: comboboxId, listboxId: listboxId, optionIdPrefix: optionIdPrefix, inputRef: inputRef, onInputClick: onInputClick, onInputChange: onInputChange, onInputFocus: onInputFocus, onInputBlur: onInputBlur, onInputKeyDown: onInputKeyDown, onSearchIconClick: onSearchIconClick })), /*#__PURE__*/React.createElement(LookupDropdown, { portalClassName: containerClassNames, opened: opened, loading: loading, listboxId: listboxId, dropdownRef: dropdownRef, listHeader: listHeader, listHeaderIdSeed: listHeaderIdSeed, listFooter: listFooter, listFooterIdSeed: listFooterIdSeed, filteredData: filteredData, focusedValue: focusedValue, getOptionId: getOptionId, onOptionClick: onOptionClick, onOptionFocus: onOptionFocus, onBlur: onInputBlur, onKeyDown: onInputKeyDown })))); }, { isFormElement: true }); //# sourceMappingURL=Lookup.js.map