@rh-support/components 2.5.5 → 2.5.7
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/lib/esm/Functional/CaseContactsSelectorExternal.d.ts +2 -0
- package/lib/esm/Functional/CaseContactsSelectorExternal.d.ts.map +1 -1
- package/lib/esm/Functional/CaseContactsSelectorExternal.js +5 -5
- package/lib/esm/OwnerTypeaheadDropdown/OwnerTypeaheadDropdown.d.ts +2 -0
- package/lib/esm/OwnerTypeaheadDropdown/OwnerTypeaheadDropdown.d.ts.map +1 -1
- package/lib/esm/OwnerTypeaheadDropdown/OwnerTypeaheadDropdown.js +15 -12
- package/lib/esm/PhoneInput/FlagSvgs.js +1 -1
- package/lib/esm/TypeaheadDropdown/TypeaheadDropdown.d.ts +4 -0
- package/lib/esm/TypeaheadDropdown/TypeaheadDropdown.d.ts.map +1 -1
- package/lib/esm/TypeaheadDropdown/TypeaheadDropdown.js +60 -28
- package/package.json +4 -7
|
@@ -11,6 +11,7 @@ interface IProps extends IDClassNameProps {
|
|
|
11
11
|
selected: (IContact | ICaseNotificationAddresses)[];
|
|
12
12
|
onChange: (selectedContacts: (IContact | ICaseNotificationAddresses)[]) => void;
|
|
13
13
|
loggedInUserRights: UserAuth;
|
|
14
|
+
contactSsoUsername: string;
|
|
14
15
|
contactsToExclude?: IContact[];
|
|
15
16
|
name?: string;
|
|
16
17
|
clearButton?: boolean;
|
|
@@ -30,6 +31,7 @@ interface IProps extends IDClassNameProps {
|
|
|
30
31
|
}
|
|
31
32
|
export declare const CONTACTS_PAGE_SIZE = 10;
|
|
32
33
|
export declare const DEFAULT_CONTACTS_OFFSET: number;
|
|
34
|
+
export declare const isCustomEmailAddress: (user: INotificationContact) => user is ICaseNotificationAddresses;
|
|
33
35
|
declare const getHydraContactLabel: (user: INotificationContact) => string;
|
|
34
36
|
declare function CaseContactsSelectorExternal(props: IProps): React.JSX.Element;
|
|
35
37
|
export { CaseContactsSelectorExternal, getHydraContactLabel };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CaseContactsSelectorExternal.d.ts","sourceRoot":"","sources":["../../../src/Functional/CaseContactsSelectorExternal.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,6BAA6B,EAAE,MAAM,yCAAyC,CAAC;AACxF,OAAO,EAAE,0BAA0B,EAAE,MAAM,qCAAqC,CAAC;AACjF,OAAO,EAAE,QAAQ,EAAE,MAAM,wCAAwC,CAAC;AAClE,OAAO,EAAuB,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjF,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAQxD,OAAO,KAA4D,MAAM,OAAO,CAAC;AAIjF,OAAO,EAAE,+BAA+B,EAAE,MAAM,wCAAwC,CAAC;AAEzF,MAAM,MAAM,oBAAoB,GAAG,QAAQ,GAAG,0BAA0B,CAAC;AACzE,UAAU,MAAO,SAAQ,gBAAgB;IACrC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,QAAQ,EAAE,CAAC,QAAQ,GAAG,0BAA0B,CAAC,EAAE,CAAC;IACpD,QAAQ,EAAE,CAAC,gBAAgB,EAAE,CAAC,QAAQ,GAAG,0BAA0B,CAAC,EAAE,KAAK,IAAI,CAAC;IAChF,kBAAkB,EAAE,QAAQ,CAAC;IAC7B,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,CAAC,MAAM,KAAA,EAAE,KAAK,KAAA,EAAE,GAAG,KAAA,KAAK,MAAM,GAAG,KAAK,CAAC,SAAS,CAAC;IAC/D,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,YAAY,CAAC,EAAE,6BAA6B,EAAE,CAAC;IAC/C,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,sBAAsB,CAAC,EAAE,OAAO,CAAC;IAEjC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,+BAA+B,EAAE,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;IACnF,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;CAChD;AAED,eAAO,MAAM,kBAAkB,KAAK,CAAC;AACrC,eAAO,MAAM,uBAAuB,QAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"CaseContactsSelectorExternal.d.ts","sourceRoot":"","sources":["../../../src/Functional/CaseContactsSelectorExternal.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,6BAA6B,EAAE,MAAM,yCAAyC,CAAC;AACxF,OAAO,EAAE,0BAA0B,EAAE,MAAM,qCAAqC,CAAC;AACjF,OAAO,EAAE,QAAQ,EAAE,MAAM,wCAAwC,CAAC;AAClE,OAAO,EAAuB,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjF,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAQxD,OAAO,KAA4D,MAAM,OAAO,CAAC;AAIjF,OAAO,EAAE,+BAA+B,EAAE,MAAM,wCAAwC,CAAC;AAEzF,MAAM,MAAM,oBAAoB,GAAG,QAAQ,GAAG,0BAA0B,CAAC;AACzE,UAAU,MAAO,SAAQ,gBAAgB;IACrC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,QAAQ,EAAE,CAAC,QAAQ,GAAG,0BAA0B,CAAC,EAAE,CAAC;IACpD,QAAQ,EAAE,CAAC,gBAAgB,EAAE,CAAC,QAAQ,GAAG,0BAA0B,CAAC,EAAE,KAAK,IAAI,CAAC;IAChF,kBAAkB,EAAE,QAAQ,CAAC;IAC7B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,CAAC,MAAM,KAAA,EAAE,KAAK,KAAA,EAAE,GAAG,KAAA,KAAK,MAAM,GAAG,KAAK,CAAC,SAAS,CAAC;IAC/D,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,YAAY,CAAC,EAAE,6BAA6B,EAAE,CAAC;IAC/C,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,sBAAsB,CAAC,EAAE,OAAO,CAAC;IAEjC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,+BAA+B,EAAE,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;IACnF,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;CAChD;AAED,eAAO,MAAM,kBAAkB,KAAK,CAAC;AACrC,eAAO,MAAM,uBAAuB,QAAyB,CAAC;AAE9D,eAAO,MAAM,oBAAoB,SAAU,oBAAoB,KAAG,IAAI,IAAI,0BAEzE,CAAC;AAMF,QAAA,MAAM,oBAAoB,SAAU,oBAAoB,KAAG,MAa1D,CAAC;AAEF,iBAAS,4BAA4B,CAAC,KAAK,EAAE,MAAM,qBA4NlD;AAED,OAAO,EAAE,4BAA4B,EAAE,oBAAoB,EAAE,CAAC"}
|
|
@@ -20,7 +20,7 @@ import { usePrevious } from '../hooks/usePrevious';
|
|
|
20
20
|
import { OwnerTypeaheadDropdown } from '../OwnerTypeaheadDropdown';
|
|
21
21
|
export const CONTACTS_PAGE_SIZE = 10;
|
|
22
22
|
export const DEFAULT_CONTACTS_OFFSET = CONTACTS_PAGE_SIZE - 1;
|
|
23
|
-
const isCustomEmailAddress = (user) => {
|
|
23
|
+
export const isCustomEmailAddress = (user) => {
|
|
24
24
|
return !!(user === null || user === void 0 ? void 0 : user.emailAddress);
|
|
25
25
|
};
|
|
26
26
|
const isContact = (user) => {
|
|
@@ -42,7 +42,7 @@ const getHydraContactLabel = (user) => {
|
|
|
42
42
|
return label ? label : '';
|
|
43
43
|
};
|
|
44
44
|
function CaseContactsSelectorExternal(props) {
|
|
45
|
-
const { customEmails, isInvalid, groupContactsAndEmails } = props;
|
|
45
|
+
const { customEmails, contactSsoUsername, isInvalid, groupContactsAndEmails, selected } = props;
|
|
46
46
|
const previousSelectedAccountNumber = usePrevious(props.selectedAccountNumber);
|
|
47
47
|
const [filteredContacts, setFilteredContacts] = useState([]);
|
|
48
48
|
/**
|
|
@@ -184,7 +184,7 @@ function CaseContactsSelectorExternal(props) {
|
|
|
184
184
|
* Removes contacts based on the hydra
|
|
185
185
|
*/
|
|
186
186
|
const onChipRemoved = (option) => {
|
|
187
|
-
props.onChange(
|
|
187
|
+
props.onChange([option]);
|
|
188
188
|
};
|
|
189
189
|
const canAddNew = (options, query) => {
|
|
190
190
|
if (!props.allowCustomEmailAdd)
|
|
@@ -198,7 +198,7 @@ function CaseContactsSelectorExternal(props) {
|
|
|
198
198
|
*/
|
|
199
199
|
useEffect(() => {
|
|
200
200
|
setFilteredContacts(allOptions);
|
|
201
|
-
}, [contactList.data, customEmails, allOptions]);
|
|
202
|
-
return (React.createElement(OwnerTypeaheadDropdown, { id: props.id || '', hasClearButton: true, multiple: !!props.multiple, groupContactsAndEmails: groupContactsAndEmails, selected: !isEmpty(props.selected) ? props.selected : [], options: filteredContacts, placeholder: props.placeholder || 'Search by name or username', "data-tracking-id": "external-case-contact-selector", isDisabled: isDisabled, status: isInvalid ? 'danger' : undefined, onChipRemoved: onChipRemoved, onClearQuery: onClearQuery, onQueryUpdated: onQueryUpdated, onBlur: onCustomerContactSelectBlur, onSelect: onCustomerContactSelect, canAddNew: canAddNew, getCreateNewText: props === null || props === void 0 ? void 0 : props.getCreateNewText }));
|
|
201
|
+
}, [contactList.data, customEmails, allOptions, selected]);
|
|
202
|
+
return (React.createElement(OwnerTypeaheadDropdown, { id: props.id || '', hasClearButton: true, multiple: !!props.multiple, contactSsoUsername: contactSsoUsername, groupContactsAndEmails: groupContactsAndEmails, selected: !isEmpty(props.selected) ? props.selected : [], options: filteredContacts, placeholder: props.placeholder || 'Search by name or username', "data-tracking-id": "external-case-contact-selector", isDisabled: isDisabled, status: isInvalid ? 'danger' : undefined, onChipRemoved: onChipRemoved, onClearQuery: onClearQuery, onQueryUpdated: onQueryUpdated, onBlur: onCustomerContactSelectBlur, onSelect: onCustomerContactSelect, canAddNew: canAddNew, getCreateNewText: props === null || props === void 0 ? void 0 : props.getCreateNewText, isLoading: props.isUpdating || contactList.isFetching }));
|
|
203
203
|
}
|
|
204
204
|
export { CaseContactsSelectorExternal, getHydraContactLabel };
|
|
@@ -5,9 +5,11 @@ export type IOwnerSelectorExtends = Omit<ITypeaheadDropdownProps, 'selected' | '
|
|
|
5
5
|
export interface IOwnerSelectorProps extends IOwnerSelectorExtends {
|
|
6
6
|
selected: IContact[];
|
|
7
7
|
options: IOwnerOption[];
|
|
8
|
+
contactSsoUsername: string;
|
|
8
9
|
groupContactsAndEmails?: boolean;
|
|
9
10
|
onSelect: (contacts: IContact[]) => void;
|
|
10
11
|
onChipRemoved?: (contact: IContact) => void;
|
|
12
|
+
isLoading?: boolean;
|
|
11
13
|
}
|
|
12
14
|
export interface IOwnerOption {
|
|
13
15
|
contact: IContact;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OwnerTypeaheadDropdown.d.ts","sourceRoot":"","sources":["../../../src/OwnerTypeaheadDropdown/OwnerTypeaheadDropdown.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"OwnerTypeaheadDropdown.d.ts","sourceRoot":"","sources":["../../../src/OwnerTypeaheadDropdown/OwnerTypeaheadDropdown.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,wCAAwC,CAAC;AAKlE,OAAO,KAAkB,MAAM,OAAO,CAAC;AAKvC,OAAO,EAGH,uBAAuB,EAE1B,MAAM,wCAAwC,CAAC;AAGhD,MAAM,MAAM,qBAAqB,GAAG,IAAI,CACpC,uBAAuB,EACvB,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,kBAAkB,GAAG,yBAAyB,GAAG,eAAe,GAAG,OAAO,CACnH,CAAC;AAEF,MAAM,WAAW,mBAAoB,SAAQ,qBAAqB;IAC9D,QAAQ,EAAE,QAAQ,EAAE,CAAC;IACrB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,QAAQ,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,IAAI,CAAC;IACzC,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,QAAQ,KAAK,IAAI,CAAC;IAC5C,SAAS,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IACzB,OAAO,EAAE,QAAQ,CAAC;IAClB,aAAa,CAAC,EAAE,OAAO,CAAC;CAC3B;AAcD,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,mBAAmB,qBA2HhE"}
|
|
@@ -15,23 +15,30 @@ import isEmpty from 'lodash/isEmpty';
|
|
|
15
15
|
import map from 'lodash/map';
|
|
16
16
|
import React, { useMemo } from 'react';
|
|
17
17
|
import { useTranslation } from 'react-i18next';
|
|
18
|
-
import { getHydraContactLabel } from '../Functional/CaseContactsSelectorExternal';
|
|
18
|
+
import { getHydraContactLabel, isCustomEmailAddress } from '../Functional/CaseContactsSelectorExternal';
|
|
19
19
|
import { useProgressiveLoading } from '../hooks/useProgressiveLoading';
|
|
20
20
|
import { TypeaheadDropdown, } from '../TypeaheadDropdown/TypeaheadDropdown';
|
|
21
21
|
const PAGE_SIZE = 10;
|
|
22
|
-
function getTypeaheadOptionsFromContacts(contacts) {
|
|
23
|
-
return map(contacts, (o) => ({
|
|
22
|
+
function getTypeaheadOptionsFromContacts(contacts, caseContactSsoUsername) {
|
|
23
|
+
return map(contacts, (o) => ({
|
|
24
|
+
label: getHydraContactLabel(o),
|
|
25
|
+
value: isCustomEmailAddress(o) ? o === null || o === void 0 ? void 0 : o.emailAddress : o === null || o === void 0 ? void 0 : o.ssoUsername,
|
|
26
|
+
disableDelete: o.ssoUsername === caseContactSsoUsername,
|
|
27
|
+
}));
|
|
24
28
|
}
|
|
25
29
|
export function OwnerTypeaheadDropdown(props) {
|
|
26
|
-
const { groupContactsAndEmails, options, selected, onSelect,
|
|
27
|
-
const selectedTypeaheadOptions = useMemo(() => getTypeaheadOptionsFromContacts(selected), [selected]);
|
|
30
|
+
const { contactSsoUsername, groupContactsAndEmails, options, selected, onSelect, onToggleClosed, onChipRemoved } = props, restProps = __rest(props, ["contactSsoUsername", "groupContactsAndEmails", "options", "selected", "onSelect", "onToggleClosed", "onChipRemoved"]);
|
|
31
|
+
const selectedTypeaheadOptions = useMemo(() => getTypeaheadOptionsFromContacts(selected, contactSsoUsername), [selected, contactSsoUsername]);
|
|
28
32
|
const { t } = useTranslation();
|
|
29
33
|
const { visibleItems, hasMoreItems, onHandleLoadMore, resetVisibleItems } = useProgressiveLoading(options, PAGE_SIZE);
|
|
30
34
|
const typeaheadOptions = useMemo(() => {
|
|
31
35
|
const contacts = [];
|
|
32
36
|
const customEmails = [];
|
|
33
37
|
for (const option of visibleItems) {
|
|
34
|
-
const typeaheadOption = {
|
|
38
|
+
const typeaheadOption = {
|
|
39
|
+
label: getHydraContactLabel(option.contact),
|
|
40
|
+
value: option.contact.ssoUsername,
|
|
41
|
+
};
|
|
35
42
|
if (option.isCustomEmail) {
|
|
36
43
|
customEmails.push(typeaheadOption);
|
|
37
44
|
}
|
|
@@ -70,10 +77,6 @@ export function OwnerTypeaheadDropdown(props) {
|
|
|
70
77
|
const selectedContacts = map(filter(options, (option) => !!find(selectedOptions, (selectedOption) => selectedOption.value === option.contact.ssoUsername)), (o) => o.contact);
|
|
71
78
|
onSelect(selectedContacts);
|
|
72
79
|
};
|
|
73
|
-
const onLocalBlur = (event) => {
|
|
74
|
-
resetVisibleItems();
|
|
75
|
-
!!onBlur && onBlur(event);
|
|
76
|
-
};
|
|
77
80
|
const onLocalToggleClosed = () => {
|
|
78
81
|
resetVisibleItems();
|
|
79
82
|
!!onToggleClosed && onToggleClosed();
|
|
@@ -83,7 +86,7 @@ export function OwnerTypeaheadDropdown(props) {
|
|
|
83
86
|
* @param option The option that is to be removed.
|
|
84
87
|
*/
|
|
85
88
|
const onLocalChipRemoved = (option) => {
|
|
86
|
-
const contact = find(selected, (o) => o.ssoUsername === option.value);
|
|
89
|
+
const contact = find(selected, (o) => (o === null || o === void 0 ? void 0 : o.ssoUsername) === option.value || (o === null || o === void 0 ? void 0 : o.emailAddress) === option.value);
|
|
87
90
|
if (contact && !!onChipRemoved) {
|
|
88
91
|
onChipRemoved(contact);
|
|
89
92
|
}
|
|
@@ -94,5 +97,5 @@ export function OwnerTypeaheadDropdown(props) {
|
|
|
94
97
|
};
|
|
95
98
|
onSelect([newCustomOption]);
|
|
96
99
|
};
|
|
97
|
-
return (React.createElement(TypeaheadDropdown, Object.assign({ "data-tracking-id": "external-case-contact-selector", selected: selectedTypeaheadOptions, options: typeaheadOptions, onSelect: onSelectContact, onHandleLoadMore: onHandleLoadMore, isShowMoreOptionVisible: hasMoreItems(),
|
|
100
|
+
return (React.createElement(TypeaheadDropdown, Object.assign({ "data-tracking-id": "external-case-contact-selector", selected: selectedTypeaheadOptions, options: typeaheadOptions, onSelect: onSelectContact, onHandleLoadMore: onHandleLoadMore, isShowMoreOptionVisible: hasMoreItems(), onToggleClosed: onLocalToggleClosed, onChipRemoved: onLocalChipRemoved, onNew: onLocalNew }, restProps)));
|
|
98
101
|
}
|
|
@@ -587,7 +587,7 @@ export const FlagSvgs = () => {
|
|
|
587
587
|
React.createElement("clipPath", { id: "clip0_301_1229" },
|
|
588
588
|
React.createElement("rect", { width: "513", height: "341.967", fill: "white", transform: "translate(0 0.65918)" })))),
|
|
589
589
|
React.createElement("symbol", { viewBox: "0 0 513 343", id: "cc_fr" },
|
|
590
|
-
React.createElement("g", {
|
|
590
|
+
React.createElement("g", { clipPath: "url(#clip0_301_1221)" },
|
|
591
591
|
React.createElement("path", { d: "M0 0.925293H513V342.929H0V0.925293Z", fill: "white" }),
|
|
592
592
|
React.createElement("path", { d: "M0 0.925293H170.996V342.929H0V0.925293Z", fill: "#0052B4" }),
|
|
593
593
|
React.createElement("path", { d: "M342.004 0.925293H513V342.929H342.004V0.925293Z", fill: "#D80027" })),
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { LabelProps } from '@patternfly/react-core';
|
|
1
2
|
import React from 'react';
|
|
2
3
|
export interface ITypeaheadDropdownProps {
|
|
3
4
|
selected: ITypeaheadDropdownOption[];
|
|
@@ -11,6 +12,8 @@ export interface ITypeaheadDropdownProps {
|
|
|
11
12
|
hasClearButton?: boolean;
|
|
12
13
|
defaultIsOpen?: boolean;
|
|
13
14
|
status?: 'success' | 'warning' | 'danger' | undefined;
|
|
15
|
+
isLoading?: boolean;
|
|
16
|
+
color?: LabelProps['color'];
|
|
14
17
|
onSelect: (options: ITypeaheadDropdownOption[]) => void;
|
|
15
18
|
onBlur?: (event: React.FocusEvent<HTMLDivElement>) => void;
|
|
16
19
|
onToggleClosed?: () => void;
|
|
@@ -27,6 +30,7 @@ export interface ITypeaheadDropdownOption {
|
|
|
27
30
|
value: any;
|
|
28
31
|
label: string;
|
|
29
32
|
group?: string;
|
|
33
|
+
disableDelete?: boolean;
|
|
30
34
|
}
|
|
31
35
|
export interface ITypeaheadDropdownGroup {
|
|
32
36
|
groupLabel: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TypeaheadDropdown.d.ts","sourceRoot":"","sources":["../../../src/TypeaheadDropdown/TypeaheadDropdown.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"TypeaheadDropdown.d.ts","sourceRoot":"","sources":["../../../src/TypeaheadDropdown/TypeaheadDropdown.tsx"],"names":[],"mappings":"AAAA,OAAO,EAIH,UAAU,EAWb,MAAM,wBAAwB,CAAC;AAOhC,OAAO,KAAsC,MAAM,OAAO,CAAC;AAM3D,MAAM,WAAW,uBAAuB;IACpC,QAAQ,EAAE,wBAAwB,EAAE,CAAC;IACrC,OAAO,EAAE,+BAA+B,EAAE,CAAC;IAC3C,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,MAAM,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;IACtD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;IAE5B,QAAQ,EAAE,CAAC,OAAO,EAAE,wBAAwB,EAAE,KAAK,IAAI,CAAC;IACxD,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,cAAc,CAAC,KAAK,IAAI,CAAC;IAC3D,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,wBAAwB,KAAK,IAAI,CAAC;IAC3D,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IACzC,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;IACxC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,+BAA+B,EAAE,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;IACnF,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;CAChD;AAED,MAAM,WAAW,wBAAwB;IACrC,KAAK,EAAE,GAAG,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,uBAAuB;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,wBAAwB,EAAE,CAAC;CACvC;AAED,MAAM,MAAM,+BAA+B,GAAG,wBAAwB,GAAG,uBAAuB,CAAC;AACjG,eAAO,MAAM,sBAAsB,2BAA2B,CAAC;AAC/D,eAAO,MAAM,oBAAoB,qBAAqB,CAAC;AA2BvD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,uBAAuB,qBA8V/D"}
|
|
@@ -1,16 +1,13 @@
|
|
|
1
1
|
import { Button, Label, LabelGroup, MenuToggle, Select, SelectGroup, SelectList, SelectOption, Spinner, TextInputGroup, TextInputGroupMain, TextInputGroupUtilities, } from '@patternfly/react-core';
|
|
2
2
|
import TimesCircleIcon from '@patternfly/react-icons/dist/js/icons/times-circle-icon';
|
|
3
3
|
import { haltEvent } from '@rh-support/utils';
|
|
4
|
-
import concat from 'lodash/concat';
|
|
5
|
-
import filter from 'lodash/filter';
|
|
6
4
|
import find from 'lodash/find';
|
|
7
5
|
import isEmpty from 'lodash/isEmpty';
|
|
8
|
-
import isEqual from 'lodash/isEqual';
|
|
9
6
|
import isNumber from 'lodash/isNumber';
|
|
10
7
|
import isString from 'lodash/isString';
|
|
11
|
-
import React, { useEffect, useState } from 'react';
|
|
12
|
-
import { Highlighter } from 'react-bootstrap-typeahead';
|
|
8
|
+
import React, { useEffect, useRef, useState } from 'react';
|
|
13
9
|
import { useTranslation } from 'react-i18next';
|
|
10
|
+
import { usePrevious } from '../hooks/usePrevious';
|
|
14
11
|
import { useSelectKeyboardNavigator } from '../hooks/useSelectKeyboardNavigator';
|
|
15
12
|
export const VIEW_MORE_OPTION_VALUE = 'view-more-option-value';
|
|
16
13
|
export const ADD_NEW_OPTION_VALUE = 'new-option-value';
|
|
@@ -37,11 +34,13 @@ function flattenOptions(options) {
|
|
|
37
34
|
}
|
|
38
35
|
export function TypeaheadDropdown(props) {
|
|
39
36
|
var _a;
|
|
40
|
-
const { options, selected, hasClearButton, id, isDisabled, multiple, placeholder, isShowMoreOptionVisible, defaultIsOpen, inputAriaControls, status, onSelect, onBlur, onToggleClosed, onClearQuery, onChipRemoved, onQueryUpdated, onHandleLoadMore, onOpenChange, onNew, canAddNew, getCreateNewText, } = props;
|
|
37
|
+
const { color, options, selected, hasClearButton, id, isDisabled, multiple, placeholder, isShowMoreOptionVisible, defaultIsOpen, inputAriaControls, status, onSelect, onBlur, onToggleClosed, onClearQuery, onChipRemoved, onQueryUpdated, onHandleLoadMore, onOpenChange, onNew, canAddNew, getCreateNewText, isLoading, } = props;
|
|
41
38
|
const { t } = useTranslation();
|
|
42
39
|
const [isOpen, setIsOpen] = useState(defaultIsOpen !== null && defaultIsOpen !== void 0 ? defaultIsOpen : false);
|
|
43
40
|
const [query, setQuery] = useState(!multiple ? (!isEmpty(selected) ? selected[0].label : '') : '');
|
|
44
41
|
const [allOptions, setAllOptions] = useState((_a = flattenOptions(options)) !== null && _a !== void 0 ? _a : []);
|
|
42
|
+
const prevSelected = usePrevious(selected);
|
|
43
|
+
const inputRef = useRef();
|
|
45
44
|
const { focusedItemIndex, onInputKeyDown, setFocusedItemIndex } = useSelectKeyboardNavigator({
|
|
46
45
|
ignoreResetOnListChange: true,
|
|
47
46
|
isDisabled: isDisabled,
|
|
@@ -52,19 +51,38 @@ export function TypeaheadDropdown(props) {
|
|
|
52
51
|
});
|
|
53
52
|
/**
|
|
54
53
|
* Allows the select toggle component to open and close itself.
|
|
54
|
+
* Resets the query for single select if the dropdown is going to be closed.
|
|
55
55
|
*/
|
|
56
56
|
const handleToggle = () => {
|
|
57
57
|
setIsOpen((open) => {
|
|
58
|
+
var _a, _b;
|
|
58
59
|
const isOpen = !open;
|
|
60
|
+
if (!isEmpty(selected) && !multiple && !isOpen) {
|
|
61
|
+
setQuery((_b = (_a = selected[0]) === null || _a === void 0 ? void 0 : _a.label) !== null && _b !== void 0 ? _b : '');
|
|
62
|
+
}
|
|
59
63
|
return isOpen;
|
|
60
64
|
});
|
|
61
65
|
};
|
|
66
|
+
/**
|
|
67
|
+
* Opens the dropdown on click if it is not open.
|
|
68
|
+
*/
|
|
69
|
+
const handleInputToggle = () => {
|
|
70
|
+
if (!isOpen) {
|
|
71
|
+
setIsOpen(true);
|
|
72
|
+
}
|
|
73
|
+
else if (isEmpty(query)) {
|
|
74
|
+
setIsOpen(false);
|
|
75
|
+
}
|
|
76
|
+
};
|
|
62
77
|
/**
|
|
63
78
|
* Set the query to an empty string when the clear button is pressed.
|
|
64
79
|
*/
|
|
65
80
|
const handleClearQuery = (event) => {
|
|
81
|
+
var _a;
|
|
66
82
|
setQuery('');
|
|
67
83
|
onClearQuery && onClearQuery();
|
|
84
|
+
(_a = inputRef === null || inputRef === void 0 ? void 0 : inputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
85
|
+
setIsOpen(true);
|
|
68
86
|
event === null || event === void 0 ? void 0 : event.stopPropagation();
|
|
69
87
|
event === null || event === void 0 ? void 0 : event.preventDefault();
|
|
70
88
|
};
|
|
@@ -76,17 +94,22 @@ export function TypeaheadDropdown(props) {
|
|
|
76
94
|
const updateQuery = (event, v) => {
|
|
77
95
|
setQuery(v);
|
|
78
96
|
onQueryUpdated && onQueryUpdated(v);
|
|
97
|
+
setFocusedItemIndex(null);
|
|
79
98
|
if (!isOpen) {
|
|
80
99
|
setIsOpen(true);
|
|
81
100
|
}
|
|
82
101
|
};
|
|
83
102
|
/**
|
|
84
103
|
* Used by the Select patternfly component to change the toggle open state.
|
|
85
|
-
* @param
|
|
104
|
+
* @param newIsOpen The state used to change the open state of the toggle
|
|
86
105
|
*/
|
|
87
|
-
const localOnOpenChange = (
|
|
88
|
-
|
|
89
|
-
|
|
106
|
+
const localOnOpenChange = (newIsOpen) => {
|
|
107
|
+
var _a, _b;
|
|
108
|
+
if (!isEmpty(selected) && !multiple && !newIsOpen) {
|
|
109
|
+
setQuery((_b = (_a = selected[0]) === null || _a === void 0 ? void 0 : _a.label) !== null && _b !== void 0 ? _b : '');
|
|
110
|
+
}
|
|
111
|
+
setIsOpen(newIsOpen);
|
|
112
|
+
!!onOpenChange && onOpenChange(newIsOpen);
|
|
90
113
|
};
|
|
91
114
|
const isAlreadySelected = (option) => {
|
|
92
115
|
return !!find(selected, (selectedOption) => selectedOption.value === option.value);
|
|
@@ -120,28 +143,28 @@ export function TypeaheadDropdown(props) {
|
|
|
120
143
|
// Single selection: replace the selection with the new option
|
|
121
144
|
onSelect([selectedOption]);
|
|
122
145
|
setQuery(selectedOption.label);
|
|
146
|
+
!!onQueryUpdated && onQueryUpdated(selectedOption.label);
|
|
123
147
|
}
|
|
124
148
|
else {
|
|
125
|
-
|
|
126
|
-
const updatedSelection = isAlreadySelected(selectedOption)
|
|
127
|
-
? filter(selected, (o) => !isEqual(selectedOption, o)) // Remove
|
|
128
|
-
: concat(selected, selectedOption); // Add
|
|
129
|
-
onSelect(updatedSelection);
|
|
149
|
+
onSelect([selectedOption]);
|
|
130
150
|
setQuery('');
|
|
151
|
+
!!onQueryUpdated && onQueryUpdated('');
|
|
131
152
|
}
|
|
132
153
|
setIsOpen(false);
|
|
133
154
|
setFocusedItemIndex(null);
|
|
134
155
|
};
|
|
135
|
-
const toggle = (toggleRef) =>
|
|
136
|
-
React.createElement(
|
|
137
|
-
React.createElement(
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
React.createElement(
|
|
144
|
-
|
|
156
|
+
const toggle = (toggleRef) => {
|
|
157
|
+
return (React.createElement(MenuToggle, { isFullWidth: true, variant: "typeahead", onClick: handleToggle, innerRef: toggleRef, isExpanded: isOpen, isDisabled: isDisabled, status: status },
|
|
158
|
+
React.createElement(TextInputGroup, { isPlain: true },
|
|
159
|
+
React.createElement(TextInputGroupMain, { value: query, placeholder: placeholder !== null && placeholder !== void 0 ? placeholder : t(`Search by name or username`), innerRef: inputRef, onChange: updateQuery, onClick: handleInputToggle, onKeyDown: onInputKeyDown, isExpanded: isOpen, "aria-controls": inputAriaControls, role: "combobox" }, !!multiple && (React.createElement(LabelGroup, { "aria-label": "Current selections" }, selected.map((option, index) => (React.createElement(Label, { key: index, variant: "outline", onClick: haltEvent, color: color !== null && color !== void 0 ? color : 'blue', isDisabled: isDisabled || (option === null || option === void 0 ? void 0 : option.disableDelete), onClose: (ev) => {
|
|
160
|
+
haltEvent(ev);
|
|
161
|
+
!!onChipRemoved && onChipRemoved(option);
|
|
162
|
+
} }, option.label)))))),
|
|
163
|
+
React.createElement(TextInputGroupUtilities, null,
|
|
164
|
+
query && hasClearButton && !isDisabled && (React.createElement(Button, { "aria-label": "Clear input value", variant: "plain", onClick: handleClearQuery, isDisabled: isDisabled },
|
|
165
|
+
React.createElement(TimesCircleIcon, null))),
|
|
166
|
+
isLoading && React.createElement(Spinner, { size: "sm" })))));
|
|
167
|
+
};
|
|
145
168
|
/**
|
|
146
169
|
* Renders the options and group options.
|
|
147
170
|
* @returns {JSX.Element[]} The rendered options.
|
|
@@ -191,8 +214,8 @@ export function TypeaheadDropdown(props) {
|
|
|
191
214
|
else if (option.value === ADD_NEW_OPTION_VALUE) {
|
|
192
215
|
return (React.createElement(SelectOption, { key: option.value, value: option.value, isFocused: false, isSelected: false }, !!getCreateNewText ? getCreateNewText(query) : `${option.label}: ${query}`));
|
|
193
216
|
}
|
|
194
|
-
|
|
195
|
-
|
|
217
|
+
const isSelected = isAlreadySelected(option);
|
|
218
|
+
return (React.createElement(SelectOption, { key: option.value, value: option.value, isFocused: focusedItemIndex === index, isSelected: isSelected, isDisabled: isSelected }, option.label));
|
|
196
219
|
};
|
|
197
220
|
useEffect(() => {
|
|
198
221
|
const localAllOptions = [...flattenOptions(options)];
|
|
@@ -206,13 +229,22 @@ export function TypeaheadDropdown(props) {
|
|
|
206
229
|
// There is no need to recall this when canAddNew has been changed.
|
|
207
230
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
208
231
|
}, [options, isShowMoreOptionVisible, query]);
|
|
232
|
+
/**
|
|
233
|
+
* Will set the query to the currently selected label if the previous selection
|
|
234
|
+
* was empty and the dropdown is single select.
|
|
235
|
+
*/
|
|
236
|
+
useEffect(() => {
|
|
237
|
+
if (!multiple && isEmpty(prevSelected) && !isEmpty(selected)) {
|
|
238
|
+
setQuery(selected[0].label);
|
|
239
|
+
}
|
|
240
|
+
}, [selected, prevSelected, isOpen, multiple]);
|
|
209
241
|
useEffect(() => {
|
|
210
242
|
if (!isOpen) {
|
|
211
243
|
setFocusedItemIndex(null);
|
|
212
244
|
!!onToggleClosed && onToggleClosed();
|
|
213
245
|
}
|
|
214
246
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
215
|
-
}, [isOpen]);
|
|
247
|
+
}, [isOpen, selected]);
|
|
216
248
|
return (React.createElement(Select, { id: id || '', "data-tracking-id": "external-case-contact-selector", role: "menu", shouldFocusFirstItemOnOpen: false, shouldFocusToggleOnSelect: false, isOpen: isOpen, onOpenChange: localOnOpenChange, toggle: toggle, popperProps: { direction: 'down', enableFlip: false }, isScrollable: true, onBlur: onBlur, onSelect: onLocalSelect },
|
|
217
249
|
React.createElement(SelectList, { isAriaMultiselectable: multiple }, ...renderOptions())));
|
|
218
250
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rh-support/components",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.7",
|
|
4
4
|
"description": "Contains all reusabel components for support app",
|
|
5
5
|
"author": "Vikas Rathee <vrathee@redhat.com>",
|
|
6
6
|
"license": "ISC",
|
|
@@ -55,7 +55,6 @@
|
|
|
55
55
|
"lodash": "^4.17.21",
|
|
56
56
|
"mark.js": "^8.11.1",
|
|
57
57
|
"react": "18.2.0",
|
|
58
|
-
"react-bootstrap-typeahead": "^5.1.4",
|
|
59
58
|
"react-router-dom": "^5.1.2",
|
|
60
59
|
"react-toastify": "^5.4.1",
|
|
61
60
|
"use-deep-compare-effect": "^1.6.1"
|
|
@@ -69,15 +68,14 @@
|
|
|
69
68
|
"@patternfly/react-table": "5.4.2",
|
|
70
69
|
"@patternfly/react-tokens": "^5.4.0",
|
|
71
70
|
"@rh-support/types": "2.0.5",
|
|
72
|
-
"@rh-support/user-permissions": "2.5.
|
|
73
|
-
"@rh-support/utils": "2.5.
|
|
71
|
+
"@rh-support/user-permissions": "2.5.3",
|
|
72
|
+
"@rh-support/utils": "2.5.3",
|
|
74
73
|
"dompurify": "^2.2.6",
|
|
75
74
|
"js-worker-search": "^1.4.1",
|
|
76
75
|
"lazysizes": "^5.3.2",
|
|
77
76
|
"lodash": "^4.17.21",
|
|
78
77
|
"mark.js": "^8.11.1",
|
|
79
78
|
"react": "18.2.0",
|
|
80
|
-
"react-bootstrap-typeahead": "^5.1.4",
|
|
81
79
|
"react-dom": "18.2.0",
|
|
82
80
|
"react-i18next": "^15.0.1",
|
|
83
81
|
"react-router-dom": "^5.1.2",
|
|
@@ -99,7 +97,6 @@
|
|
|
99
97
|
"@types/marked": "^1.1.0",
|
|
100
98
|
"@types/node": "^20.11.5",
|
|
101
99
|
"@types/react": "^18.2.20",
|
|
102
|
-
"@types/react-bootstrap-typeahead": "^5.1.3",
|
|
103
100
|
"@types/react-dom": "^18.2.18",
|
|
104
101
|
"identity-obj-proxy": "^3.0.0",
|
|
105
102
|
"jest": "^29.7.0",
|
|
@@ -109,5 +106,5 @@
|
|
|
109
106
|
"defaults and supports es6-module",
|
|
110
107
|
"maintained node versions"
|
|
111
108
|
],
|
|
112
|
-
"gitHead": "
|
|
109
|
+
"gitHead": "5eaf1c740ed00678417977760f52519d0ac85ee9"
|
|
113
110
|
}
|