first commit

This commit is contained in:
Stefan Hacker
2026-04-03 09:38:48 +02:00
commit 37ad745546
47450 changed files with 3120798 additions and 0 deletions
@@ -0,0 +1 @@
export * from '../../Autofill/Autofill';
@@ -0,0 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
// Deprecated, import directly from the component folder now.
tslib_1.__exportStar(require("../../Autofill/Autofill"), exports);
//# sourceMappingURL=BaseAutoFill.js.map
@@ -0,0 +1 @@
{"version":3,"file":"BaseAutoFill.js","sourceRoot":"../src/","sources":["components/pickers/AutoFill/BaseAutoFill.tsx"],"names":[],"mappings":";;;AAAA,6DAA6D;AAC7D,kEAAwC","sourcesContent":["// Deprecated, import directly from the component folder now.\nexport * from '../../Autofill/Autofill';\n"]}
@@ -0,0 +1 @@
export * from '../../Autofill/Autofill.types';
@@ -0,0 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
// Deprecated, import directly from the component folder now.
tslib_1.__exportStar(require("../../Autofill/Autofill.types"), exports);
//# sourceMappingURL=BaseAutoFill.types.js.map
@@ -0,0 +1 @@
{"version":3,"file":"BaseAutoFill.types.js","sourceRoot":"../src/","sources":["components/pickers/AutoFill/BaseAutoFill.types.ts"],"names":[],"mappings":";;;AAAA,6DAA6D;AAC7D,wEAA8C","sourcesContent":["// Deprecated, import directly from the component folder now.\nexport * from '../../Autofill/Autofill.types';\n"]}
@@ -0,0 +1,176 @@
import * as React from 'react';
import { KeyCodes, IStyleFunctionOrObject } from '../../Utilities';
import { Selection } from '../../utilities/selection/index';
import { Suggestions } from './Suggestions/Suggestions';
import { SuggestionsController } from './Suggestions/SuggestionsController';
import { Autofill } from '../Autofill/index';
import type { ISuggestions, ISuggestionsProps } from './Suggestions/Suggestions.types';
import type { IBasePicker, IBasePickerProps } from './BasePicker.types';
import type { IAutofill } from '../Autofill/index';
import type { ILabelStyleProps, ILabelStyles } from '../../Label';
import type { ICalloutContentStyleProps, ICalloutContentStyles } from '../../Callout';
import type { JSXElement } from '@fluentui/utilities';
export interface IBasePickerState<T> {
items?: any;
suggestedDisplayValue?: string;
moreSuggestionsAvailable?: boolean;
isFocused?: boolean;
isSearching?: boolean;
isMostRecentlyUsedVisible?: boolean;
suggestionsVisible?: boolean;
suggestionsLoading?: boolean;
suggestionsExtendedLoading?: boolean;
isResultsFooterVisible?: boolean;
selectedIndices?: number[];
selectionRemoved?: T;
errorMessage?: string | JSXElement;
}
/**
* Aria id's for internal picker components
* {@docCategory Pickers}
*/
export type IPickerAriaIds = {
/**
* Aria id for selected suggestion alert component
*/
selectedSuggestionAlert: string;
/**
* Aria id for selected items container component
*/
selectedItems: string;
/**
* Aria id for suggestions list component
*/
suggestionList: string;
/**
* Aria id for element with role=combobox
*/
combobox: string;
/**
* Aria id for error message component
*/
error: string;
};
/**
* {@docCategory Pickers}
*/
export declare class BasePicker<T extends {}, P extends IBasePickerProps<T>> extends React.Component<P, IBasePickerState<T>> implements IBasePicker<T> {
static contextType: React.Context<import("@fluentui/react-window-provider").WindowProviderProps>;
context: any;
protected root: React.RefObject<HTMLDivElement | null>;
protected input: React.RefObject<IAutofill | null>;
protected suggestionElement: React.RefObject<ISuggestions<T> | null>;
protected selection: Selection;
protected suggestionStore: SuggestionsController<T>;
/**
* @deprecated this is no longer necessary as typescript now supports generic elements
*/
protected SuggestionOfProperType: new (props: ISuggestionsProps<T>) => Suggestions<T>;
protected currentPromise: PromiseLike<any> | undefined;
protected _ariaMap: IPickerAriaIds;
private _styledSuggestions;
private _id;
private _async;
private _isMounted;
private _onResolveSuggestionsDebounced;
private _overrideScrollDismiss;
private _overrideScrollDimissTimeout;
static getDerivedStateFromProps(newProps: IBasePickerProps<any>): IBasePickerState<any> | null;
constructor(basePickerProps: P);
get items(): T[];
componentDidMount(): void;
componentDidUpdate(oldProps: P, oldState: IBasePickerState<T>): void;
componentWillUnmount(): void;
focus(): void;
focusInput(): void;
dismissSuggestions: (ev?: any) => void;
completeSuggestion(forceComplete?: boolean): void;
refocusSuggestions: (keyCode: KeyCodes) => void;
render(): JSXElement;
protected _getDescribedBy: (items: T[], hasError: boolean) => string;
protected canAddItems(): boolean;
protected renderLabel(inputId: string, styles: IStyleFunctionOrObject<ILabelStyleProps, ILabelStyles> | undefined): JSXElement | null;
protected renderError(className?: string): JSXElement | null;
protected renderSuggestions(styles: IStyleFunctionOrObject<ICalloutContentStyleProps, ICalloutContentStyles> | undefined): JSXElement | null;
protected renderItems(): JSXElement[];
protected resetFocus(index?: number): void;
protected onSuggestionSelect(): void;
protected onSelectionChange(): void;
protected updateSuggestions(suggestions: any[]): void;
/**
* Only to be called when there is nothing in the input. Checks to see if the consumer has
* provided a function to resolve suggestions
*/
protected onEmptyInputFocus(): void;
protected updateValue(updatedValue: string): void;
protected updateSuggestionsList(suggestions: T[] | PromiseLike<T[]>, updatedValue?: string): void;
protected resolveNewValue(updatedValue: string, suggestions: T[]): void;
protected onChange(items?: T[]): void;
protected onInputChange: (value: string) => void;
protected onSuggestionClick: (ev: React.MouseEvent<HTMLElement>, item: any, index: number) => void;
protected onSuggestionRemove: (ev: React.MouseEvent<HTMLElement>, item: T, index: number) => void;
protected onInputFocus: (ev: React.FocusEvent<HTMLInputElement | Autofill>) => void;
protected onInputBlur: (ev: React.FocusEvent<HTMLInputElement | Autofill>) => void;
protected onBlur: (ev: React.FocusEvent<HTMLElement | Autofill>) => void;
/**
* Resets focus to last element in wrapper div if clicking back into Picker that has hit item limit
*/
protected onWrapperClick: (ev: React.MouseEvent<HTMLInputElement>) => void;
/**
* Reveals suggestions any time the user clicks on the input element
* without shifting focus.
*/
protected onClick: (ev: React.MouseEvent<HTMLInputElement>) => void;
protected onFocus: () => void;
protected onKeyDown: (ev: React.KeyboardEvent<HTMLElement>) => void;
protected onItemChange: (changedItem: T, index: number) => void;
protected onGetMoreResults: () => void;
protected completeSelection: (item: T) => void;
protected addItemByIndex: (index: number) => void;
protected addItem: (item: T) => void;
protected removeItem: (item: T) => void;
protected removeItems: (itemsToRemove: any[]) => void;
protected onBackspace(ev: React.KeyboardEvent<HTMLElement>): void;
/**
* @deprecated this is no longer necessary as focuszone has been removed
*/
protected _shouldFocusZoneEnterInnerZone: (ev: React.KeyboardEvent<HTMLElement>) => boolean;
protected getActiveDescendant(): string | undefined;
/** @deprecated use renderCustomAlert instead */
protected getSuggestionsAlert(suggestionAlertClassName?: string): JSXElement | undefined;
protected renderCustomAlert(alertClassName?: string): JSXElement;
private _preventDismissOnScrollOrResize;
/** If suggestions are still loading after a predefined amount of time, set state to show user alert */
private _startLoadTimer;
/**
* Takes in the current updated value and either resolves it with the new suggestions
* or if updated value is undefined then it clears out currently suggested items
*/
private _updateAndResolveValue;
private _getErrorMessage;
private _updateErrorMessage;
/**
* Controls what happens whenever there is an action that impacts the selected items.
* If `selectedItems` is provided, this will act as a controlled component and it will not update its own state.
*/
private _updateSelectedItems;
private _onSelectedItemsUpdated;
/**
* Suggestions are normally shown after the user updates text and the text
* is non-empty, but also when the user clicks on the input element.
* @returns True if suggestions should be shown.
*/
private _getShowSuggestions;
private _onResolveSuggestions;
private _completeGenericSuggestion;
private _getTextFromItem;
/**
* This should be called when the user does something other than use text entry to trigger suggestions.
*
*/
private _userTriggeredSuggestions;
}
export declare class BasePickerListBelow<T extends {}, P extends IBasePickerProps<T>> extends BasePicker<T, P> {
render(): JSXElement;
protected onBackspace(ev: React.KeyboardEvent<HTMLElement>): void;
}
@@ -0,0 +1,993 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BasePickerListBelow = exports.BasePicker = void 0;
var tslib_1 = require("tslib");
var React = require("react");
var Utilities_1 = require("../../Utilities");
var Callout_1 = require("../../Callout");
var index_1 = require("../../utilities/selection/index");
var DirectionalHint_1 = require("../../common/DirectionalHint");
var Suggestions_1 = require("./Suggestions/Suggestions");
var Suggestions_styles_1 = require("./Suggestions/Suggestions.styles");
var SuggestionsController_1 = require("./Suggestions/SuggestionsController");
var BasePicker_types_1 = require("./BasePicker.types");
var index_2 = require("../Autofill/index");
var stylesImport = require("./BasePicker.scss");
var Label_1 = require("../../Label");
var react_window_provider_1 = require("@fluentui/react-window-provider");
var dom_1 = require("../../utilities/dom");
var legacyStyles = stylesImport;
var EXTENDED_LOAD_TIME = 3000;
var getClassNames = (0, Utilities_1.classNamesFunction)();
/**
* Should be removed once new picker without inheritance is created
*/
function getStyledSuggestions(suggestionsType) {
return (0, Utilities_1.styled)(suggestionsType, Suggestions_styles_1.getStyles, undefined, {
scope: 'Suggestions',
});
}
/**
* {@docCategory Pickers}
*/
var BasePicker = /** @class */ (function (_super) {
tslib_1.__extends(BasePicker, _super);
function BasePicker(basePickerProps) {
var _this = _super.call(this, basePickerProps) || this;
// Refs
_this.root = React.createRef();
_this.input = React.createRef();
_this.suggestionElement = React.createRef();
/**
* @deprecated this is no longer necessary as typescript now supports generic elements
*/
_this.SuggestionOfProperType = Suggestions_1.Suggestions;
// eslint-disable-next-line @typescript-eslint/no-deprecated
_this._styledSuggestions = getStyledSuggestions(_this.SuggestionOfProperType);
_this._isMounted = false;
_this._overrideScrollDismiss = false;
_this.dismissSuggestions = function (ev) {
var selectItemFunction = function () {
var addItemOnDismiss = true;
if (_this.props.onDismiss) {
addItemOnDismiss = _this.props.onDismiss(ev, _this.suggestionStore.currentSuggestion ? _this.suggestionStore.currentSuggestion.item : undefined);
}
if (!ev || (ev && !ev.defaultPrevented)) {
// Select the first suggestion if one is available and permitted by onDismiss when user leaves.
if (addItemOnDismiss !== false &&
_this.canAddItems() &&
_this.suggestionStore.hasSelectedSuggestion() &&
_this.state.suggestedDisplayValue) {
_this.addItemByIndex(0);
}
}
};
if (_this.currentPromise) {
_this.currentPromise.then(function () { return selectItemFunction(); });
}
else {
selectItemFunction();
}
_this.setState({ suggestionsVisible: false });
};
_this.refocusSuggestions = function (keyCode) {
_this.resetFocus();
if (_this.suggestionStore.suggestions && _this.suggestionStore.suggestions.length > 0) {
if (keyCode === Utilities_1.KeyCodes.up) {
_this.suggestionStore.setSelectedSuggestion(_this.suggestionStore.suggestions.length - 1);
}
else if (keyCode === Utilities_1.KeyCodes.down) {
_this.suggestionStore.setSelectedSuggestion(0);
}
}
};
_this._getDescribedBy = function (items, hasError) {
var describedBy = '';
if (items.length > 0) {
describedBy += _this._ariaMap.selectedItems + ' ';
}
if (hasError) {
describedBy += _this._ariaMap.error;
}
return describedBy;
};
_this.onInputChange = function (value) {
_this.updateValue(value);
_this.setState({
moreSuggestionsAvailable: true,
isMostRecentlyUsedVisible: false,
});
};
_this.onSuggestionClick = function (ev, item, index) {
_this.addItemByIndex(index);
};
_this.onSuggestionRemove = function (ev, item, index) {
if (_this.props.onRemoveSuggestion) {
_this.props.onRemoveSuggestion(item);
}
_this.suggestionStore.removeSuggestion(index);
};
_this.onInputFocus = function (ev) {
_this.selection.setAllSelected(false);
// Only trigger all of the focus if this component isn't already focused.
// For example when an item is selected or removed from the selected list it should be treated
// as though the input is still focused.
if (!_this.state.isFocused) {
_this._userTriggeredSuggestions();
if (_this.props.inputProps && _this.props.inputProps.onFocus) {
_this.props.inputProps.onFocus(ev);
}
}
};
_this.onInputBlur = function (ev) {
if (_this.props.inputProps && _this.props.inputProps.onBlur) {
_this.props.inputProps.onBlur(ev);
}
};
_this.onBlur = function (ev) {
if (_this.state.isFocused) {
// Only blur the entire component if an unrelated element gets focus.
// Otherwise treat it as though it still has focus.
// Do nothing if the blur is coming from something
// inside the comboBox root or the comboBox menu since
// it we are not really bluring from the whole comboBox
var relatedTarget = ev.relatedTarget;
if (ev.relatedTarget === null) {
// In IE11, due to lack of support, event.relatedTarget is always
// null making every onBlur call to be "outside" of the ComboBox
// even when it's not. Using document.activeElement is another way
// for us to be able to get what the relatedTarget without relying
// on the event
relatedTarget = (0, dom_1.getDocumentEx)(_this.context).activeElement;
}
if (relatedTarget && !(0, Utilities_1.elementContains)(_this.root.current, relatedTarget)) {
_this.setState({ isFocused: false });
if (_this.props.onBlur) {
_this.props.onBlur(ev);
}
}
}
};
/**
* Resets focus to last element in wrapper div if clicking back into Picker that has hit item limit
*/
_this.onWrapperClick = function (ev) {
if (_this.state.items.length && !_this.canAddItems()) {
_this.resetFocus(_this.state.items.length - 1);
}
};
/**
* Reveals suggestions any time the user clicks on the input element
* without shifting focus.
*/
_this.onClick = function (ev) {
if (_this.props.inputProps !== undefined && _this.props.inputProps.onClick !== undefined) {
_this.props.inputProps.onClick(ev);
}
// Only primary (left) clicks show suggestions.
if (ev.button === 0) {
_this._userTriggeredSuggestions();
}
};
_this.onFocus = function () {
if (!_this.state.isFocused) {
_this.setState({ isFocused: true });
}
};
_this.onKeyDown = function (ev) {
// eslint-disable-next-line @typescript-eslint/no-deprecated
var keyCode = ev.which;
switch (keyCode) {
case Utilities_1.KeyCodes.escape:
if (_this.state.suggestionsVisible) {
_this.setState({ suggestionsVisible: false });
ev.preventDefault();
ev.stopPropagation();
}
break;
case Utilities_1.KeyCodes.tab:
case Utilities_1.KeyCodes.enter:
if (_this.suggestionElement.current && _this.suggestionElement.current.hasSuggestedActionSelected()) {
_this.suggestionElement.current.executeSelectedAction();
}
else if (!ev.shiftKey && _this.suggestionStore.hasSelectedSuggestion() && _this.state.suggestionsVisible) {
_this.completeSuggestion();
ev.preventDefault();
ev.stopPropagation();
}
else {
_this._completeGenericSuggestion();
}
break;
case Utilities_1.KeyCodes.backspace:
if (!_this.props.disabled) {
_this.onBackspace(ev);
}
ev.stopPropagation();
break;
case Utilities_1.KeyCodes.del:
if (!_this.props.disabled) {
if (_this.input.current &&
ev.target === _this.input.current.inputElement &&
_this.state.suggestionsVisible &&
_this.suggestionStore.currentIndex !== -1) {
if (_this.props.onRemoveSuggestion) {
_this.props.onRemoveSuggestion(_this.suggestionStore.currentSuggestion.item);
}
_this.suggestionStore.removeSuggestion(_this.suggestionStore.currentIndex);
_this.forceUpdate();
}
else {
_this.onBackspace(ev);
}
}
ev.stopPropagation();
break;
case Utilities_1.KeyCodes.up:
if (_this.input.current && ev.target === _this.input.current.inputElement && _this.state.suggestionsVisible) {
if (_this.suggestionElement.current &&
_this.suggestionElement.current.tryHandleKeyDown(keyCode, _this.suggestionStore.currentIndex)) {
ev.preventDefault();
ev.stopPropagation();
_this.forceUpdate();
}
else {
if (_this.suggestionElement.current &&
_this.suggestionElement.current.hasSuggestedAction() &&
_this.suggestionStore.currentIndex === 0) {
ev.preventDefault();
ev.stopPropagation();
_this.suggestionElement.current.focusAboveSuggestions();
_this.suggestionStore.deselectAllSuggestions();
_this.forceUpdate();
}
else {
if (_this.suggestionStore.previousSuggestion()) {
ev.preventDefault();
ev.stopPropagation();
_this.onSuggestionSelect();
}
}
}
}
break;
case Utilities_1.KeyCodes.down:
if (_this.input.current && ev.target === _this.input.current.inputElement && _this.state.suggestionsVisible) {
if (_this.suggestionElement.current &&
_this.suggestionElement.current.tryHandleKeyDown(keyCode, _this.suggestionStore.currentIndex)) {
ev.preventDefault();
ev.stopPropagation();
_this.forceUpdate();
}
else {
if (_this.suggestionElement.current &&
_this.suggestionElement.current.hasSuggestedAction() &&
_this.suggestionStore.currentIndex + 1 === _this.suggestionStore.suggestions.length) {
ev.preventDefault();
ev.stopPropagation();
_this.suggestionElement.current.focusBelowSuggestions();
_this.suggestionStore.deselectAllSuggestions();
_this.forceUpdate();
}
else {
if (_this.suggestionStore.nextSuggestion()) {
ev.preventDefault();
ev.stopPropagation();
_this.onSuggestionSelect();
}
}
}
}
break;
}
};
_this.onItemChange = function (changedItem, index) {
var items = _this.state.items;
if (index >= 0) {
var newItems = items;
newItems[index] = changedItem;
_this._updateSelectedItems(newItems);
}
};
_this.onGetMoreResults = function () {
_this.setState({
isSearching: true,
}, function () {
if (_this.props.onGetMoreResults && _this.input.current) {
var suggestions = _this.props.onGetMoreResults(_this.input.current.value, _this.state.items);
var suggestionsArray = suggestions;
var suggestionsPromiseLike = suggestions;
if (Array.isArray(suggestionsArray)) {
_this.updateSuggestions(suggestionsArray);
_this.setState({ isSearching: false });
}
else if (suggestionsPromiseLike.then) {
suggestionsPromiseLike.then(function (newSuggestions) {
_this.updateSuggestions(newSuggestions);
_this.setState({ isSearching: false });
});
}
}
else {
_this.setState({ isSearching: false });
}
if (_this.input.current) {
_this.input.current.focus();
}
_this.setState({
moreSuggestionsAvailable: false,
isResultsFooterVisible: true,
});
});
};
_this.completeSelection = function (item) {
_this.addItem(item);
_this.updateValue('');
if (_this.input.current) {
_this.input.current.clear();
}
_this.setState({ suggestionsVisible: false });
};
_this.addItemByIndex = function (index) {
_this.completeSelection(_this.suggestionStore.getSuggestionAtIndex(index).item);
};
_this.addItem = function (item) {
var processedItem = _this.props.onItemSelected
? _this.props.onItemSelected(item)
: item;
if (processedItem === null) {
return;
}
var processedItemObject = processedItem;
var processedItemPromiseLike = processedItem;
if (processedItemPromiseLike && processedItemPromiseLike.then) {
processedItemPromiseLike.then(function (resolvedProcessedItem) {
var newItems = _this.state.items.concat([resolvedProcessedItem]);
_this._updateSelectedItems(newItems);
});
}
else {
var newItems = _this.state.items.concat([processedItemObject]);
_this._updateSelectedItems(newItems);
}
_this.setState({ suggestedDisplayValue: '', selectionRemoved: undefined });
};
_this.removeItem = function (item) {
var items = _this.state.items;
var index = items.indexOf(item);
if (index >= 0) {
var newItems = items.slice(0, index).concat(items.slice(index + 1));
_this.setState({ selectionRemoved: item });
_this._updateSelectedItems(newItems);
// reset selection removed text after a timeout so it isn't reached by screen reader virtual cursor.
// the exact timing isn't important, the live region will fully read even if the text is removed.
_this._async.setTimeout(function () {
_this.setState({ selectionRemoved: undefined });
}, 1000);
}
};
_this.removeItems = function (itemsToRemove) {
var items = _this.state.items;
var newItems = items.filter(function (item) { return itemsToRemove.indexOf(item) === -1; });
_this._updateSelectedItems(newItems);
};
/**
* @deprecated this is no longer necessary as focuszone has been removed
*/
_this._shouldFocusZoneEnterInnerZone = function (ev) {
// If suggestions are shown const up/down keys control them, otherwise allow them through to control the focusZone.
if (_this.state.suggestionsVisible) {
// eslint-disable-next-line @typescript-eslint/no-deprecated
switch (ev.which) {
case Utilities_1.KeyCodes.up:
case Utilities_1.KeyCodes.down:
return true;
}
}
// eslint-disable-next-line @typescript-eslint/no-deprecated
if (ev.which === Utilities_1.KeyCodes.enter) {
return true;
}
return false;
};
_this._onResolveSuggestions = function (updatedValue) {
var suggestions = _this.props.onResolveSuggestions(updatedValue, _this.state.items);
if (suggestions !== null) {
_this.updateSuggestionsList(suggestions, updatedValue);
}
};
_this._completeGenericSuggestion = function () {
if (_this.props.onValidateInput &&
_this.input.current &&
_this.props.onValidateInput(_this.input.current.value) !== BasePicker_types_1.ValidationState.invalid &&
_this.props.createGenericItem) {
var itemToConvert = _this.props.createGenericItem(_this.input.current.value, _this.props.onValidateInput(_this.input.current.value));
_this.suggestionStore.createGenericSuggestion(itemToConvert);
_this.completeSuggestion();
}
};
/**
* This should be called when the user does something other than use text entry to trigger suggestions.
*
*/
_this._userTriggeredSuggestions = function () {
if (!_this.state.suggestionsVisible) {
var input = _this.input.current ? _this.input.current.value : '';
if (!input) {
_this.onEmptyInputFocus();
}
else {
if (_this.suggestionStore.suggestions.length === 0) {
_this._onResolveSuggestionsDebounced(input);
}
else {
_this.setState({
isMostRecentlyUsedVisible: false,
suggestionsVisible: true,
});
}
}
}
};
(0, Utilities_1.initializeComponentRef)(_this);
var items = basePickerProps.selectedItems || basePickerProps.defaultSelectedItems || [];
_this._id = (0, Utilities_1.getId)();
_this._ariaMap = {
selectedItems: "selected-items-".concat(_this._id),
selectedSuggestionAlert: "selected-suggestion-alert-".concat(_this._id),
suggestionList: "suggestion-list-".concat(_this._id),
combobox: "combobox-".concat(_this._id),
error: "error-".concat(_this._id),
};
_this.suggestionStore = new SuggestionsController_1.SuggestionsController();
_this.selection = new index_1.Selection({ onSelectionChanged: function () { return _this.onSelectionChange(); } });
_this.selection.setItems(items);
_this.state = {
items: items,
suggestedDisplayValue: '',
isMostRecentlyUsedVisible: false,
moreSuggestionsAvailable: false,
isFocused: false,
isSearching: false,
selectedIndices: [],
selectionRemoved: undefined,
};
return _this;
}
BasePicker.getDerivedStateFromProps = function (newProps) {
if (newProps.selectedItems) {
return { items: newProps.selectedItems };
}
return null;
};
Object.defineProperty(BasePicker.prototype, "items", {
get: function () {
return this.state.items;
},
enumerable: false,
configurable: true
});
BasePicker.prototype.componentDidMount = function () {
this._isMounted = true;
this._async = new Utilities_1.Async(this);
this._updateErrorMessage(this.state.items);
this.selection.setItems(this.state.items);
this._onResolveSuggestionsDebounced = this._async.debounce(this._onResolveSuggestions, this.props.resolveDelay);
};
BasePicker.prototype.componentDidUpdate = function (oldProps, oldState) {
var _this = this;
if (this.state.items && this.state.items !== oldState.items) {
var currentSelectedIndex = this.selection.getSelectedIndices()[0];
this.selection.setItems(this.state.items);
if (this.state.isFocused) {
// Reset focus and selection so that selected item stays in sync if something
// has been removed
if (this.state.items.length < oldState.items.length) {
this.selection.setIndexSelected(currentSelectedIndex, false, true);
this.resetFocus(currentSelectedIndex);
}
// Reset focus to last item if the input is removed
else if (this.state.items.length > oldState.items.length && !this.canAddItems()) {
this.resetFocus(this.state.items.length - 1);
}
}
}
this._updateErrorMessage(this.state.items);
// handle dismiss buffer after suggestions are opened
if (this.state.suggestionsVisible && !oldState.suggestionsVisible) {
this._overrideScrollDismiss = true;
this._async.clearTimeout(this._overrideScrollDimissTimeout);
this._overrideScrollDimissTimeout = this._async.setTimeout(function () {
_this._overrideScrollDismiss = false;
}, 100);
}
};
BasePicker.prototype.componentWillUnmount = function () {
this._isMounted = false;
if (this.currentPromise) {
this.currentPromise = undefined;
}
this._async.dispose();
};
BasePicker.prototype.focus = function () {
if (this.input.current) {
this.input.current.focus();
}
};
BasePicker.prototype.focusInput = function () {
if (this.input.current) {
this.input.current.focus();
}
};
BasePicker.prototype.completeSuggestion = function (forceComplete) {
if (this.suggestionStore.hasSelectedSuggestion() && this.input.current) {
this.completeSelection(this.suggestionStore.currentSuggestion.item);
}
else if (forceComplete) {
this._completeGenericSuggestion();
}
};
BasePicker.prototype.render = function () {
var _a, _b, _c, _d;
var _e = this.state, suggestedDisplayValue = _e.suggestedDisplayValue, isFocused = _e.isFocused, items = _e.items;
var _f = this.props, className = _f.className, inputProps = _f.inputProps, disabled = _f.disabled, selectionAriaLabel = _f.selectionAriaLabel, _g = _f.selectionRole, selectionRole = _g === void 0 ? 'list' : _g, theme = _f.theme, styles = _f.styles;
var suggestionsVisible = !!this.state.suggestionsVisible;
var suggestionsAvailable = suggestionsVisible ? this._ariaMap.suggestionList : undefined;
var hasError = !!((_a = this.state.errorMessage) !== null && _a !== void 0 ? _a : this.props.errorMessage);
// TODO
// Clean this up by leaving only the first part after removing support for SASS.
// Currently we can not remove the SASS styles from BasePicker class because it
// might be used by consumers who created custom pickers from extending from
// this base class and have not used the new 'styles' prop.
// We check for 'styles' prop which is going to be injected by the 'styled' HOC
// for every other already existing picker variant (PeoplePicker, TagPicker)
// so that we can use the CSS-in-JS styles. If the check fails (ex: custom picker),
// then we just use the old SASS styles instead.
var classNames = styles
? getClassNames(styles, {
theme: theme,
className: className,
isFocused: isFocused,
disabled: disabled,
hasErrorMessage: hasError,
inputClassName: inputProps && inputProps.className,
})
: {
root: (0, Utilities_1.css)('ms-BasePicker', className ? className : ''),
error: 'ms-BasePicker-error',
text: (0, Utilities_1.css)('ms-BasePicker-text', legacyStyles.pickerText, this.state.isFocused && legacyStyles.inputFocused),
itemsWrapper: legacyStyles.pickerItems,
input: (0, Utilities_1.css)('ms-BasePicker-input', legacyStyles.pickerInput, inputProps && inputProps.className),
screenReaderText: legacyStyles.screenReaderOnly,
};
var comboLabel = this.props['aria-label'] || (inputProps === null || inputProps === void 0 ? void 0 : inputProps['aria-label']);
var inputId = (_b = inputProps === null || inputProps === void 0 ? void 0 : inputProps.id) !== null && _b !== void 0 ? _b : this._ariaMap.combobox;
// selectionAriaLabel is contained in a separate <span> rather than an aria-label on the items list
// because if the items list has an aria-label, the aria-describedby on the input will only read
// that label instead of all the selected items. Using aria-labelledby instead fixes this, since
// aria-describedby and aria-labelledby will not follow a second aria-labelledby
return (React.createElement("div", { ref: this.root, className: classNames.root, onKeyDown: this.onKeyDown, onFocus: this.onFocus, onBlur: this.onBlur, onClick: this.onWrapperClick },
this.renderLabel(inputId, (_c = classNames.subComponentStyles) === null || _c === void 0 ? void 0 : _c.label),
this.renderCustomAlert(classNames.screenReaderText),
React.createElement("span", { id: "".concat(this._ariaMap.selectedItems, "-label"), hidden: true }, selectionAriaLabel || comboLabel),
React.createElement(index_1.SelectionZone, { selection: this.selection, selectionMode: index_1.SelectionMode.multiple },
React.createElement("div", { className: classNames.text, "aria-owns": suggestionsAvailable },
items.length > 0 && (React.createElement("span", { id: this._ariaMap.selectedItems, className: classNames.itemsWrapper, role: selectionRole, "aria-labelledby": "".concat(this._ariaMap.selectedItems, "-label") }, this.renderItems())),
this.canAddItems() && (React.createElement(index_2.Autofill, tslib_1.__assign({ spellCheck: false }, inputProps, { className: classNames.input, componentRef: this.input, id: inputId, onClick: this.onClick, onFocus: this.onInputFocus, onBlur: this.onInputBlur, onInputValueChange: this.onInputChange, suggestedDisplayValue: suggestedDisplayValue, "aria-activedescendant": suggestionsVisible ? this.getActiveDescendant() : undefined, "aria-controls": suggestionsAvailable, "aria-describedby": this._getDescribedBy(items, hasError), "aria-expanded": suggestionsVisible, "aria-haspopup": "listbox", "aria-label": comboLabel, role: "combobox", disabled: disabled,
// eslint-disable-next-line @typescript-eslint/no-deprecated
onInputChange: this.props.onInputChange }))))),
this.renderError(classNames.error),
this.renderSuggestions((_d = classNames.subComponentStyles) === null || _d === void 0 ? void 0 : _d.callout)));
};
BasePicker.prototype.canAddItems = function () {
var items = this.state.items;
var itemLimit = this.props.itemLimit;
return itemLimit === undefined || items.length < itemLimit;
};
BasePicker.prototype.renderLabel = function (inputId, styles) {
var _a = this.props, label = _a.label, disabled = _a.disabled, required = _a.required;
if (!label) {
return null;
}
return (React.createElement(Label_1.Label, { className: "ms-BasePicker-label", styles: styles, disabled: disabled, required: required, htmlFor: inputId }, label));
};
BasePicker.prototype.renderError = function (className) {
var _a = this.props.errorMessage, errorMessage = _a === void 0 ? this.state.errorMessage : _a;
if (!errorMessage) {
return null;
}
return (React.createElement("div", { role: "alert", id: this._ariaMap.error, className: className }, errorMessage));
};
BasePicker.prototype.renderSuggestions = function (styles) {
var _this = this;
var StyledTypedSuggestions = this._styledSuggestions;
return this.state.suggestionsVisible && this.input ? (React.createElement(Callout_1.Callout, tslib_1.__assign({ isBeakVisible: false, gapSpace: 5, target: this.input.current ? this.input.current.inputElement : undefined, onDismiss: this.dismissSuggestions, directionalHint: DirectionalHint_1.DirectionalHint.bottomLeftEdge, directionalHintForRTL: DirectionalHint_1.DirectionalHint.bottomRightEdge,
// eslint-disable-next-line react/jsx-no-bind
preventDismissOnEvent: function (ev) { return _this._preventDismissOnScrollOrResize(ev); }, styles: styles }, this.props.pickerCalloutProps),
React.createElement(StyledTypedSuggestions
// Assumed to set in derived component's defaultProps
, tslib_1.__assign({
// Assumed to set in derived component's defaultProps
onRenderSuggestion: this.props.onRenderSuggestionsItem, onSuggestionClick: this.onSuggestionClick, onSuggestionRemove: this.onSuggestionRemove, suggestions: this.suggestionStore.getSuggestions(), componentRef: this.suggestionElement, onGetMoreResults: this.onGetMoreResults, moreSuggestionsAvailable: this.state.moreSuggestionsAvailable, isLoading: this.state.suggestionsLoading, isExtendedLoading: this.state.suggestionsExtendedLoading, isSearching: this.state.isSearching, isMostRecentlyUsedVisible: this.state.isMostRecentlyUsedVisible, isResultsFooterVisible: this.state.isResultsFooterVisible, refocusSuggestions: this.refocusSuggestions, removeSuggestionAriaLabel: this.props.removeButtonAriaLabel, suggestionsListId: this._ariaMap.suggestionList, createGenericItem: this._completeGenericSuggestion }, this.props.pickerSuggestionsProps)))) : null;
};
BasePicker.prototype.renderItems = function () {
var _this = this;
var _a = this.props, disabled = _a.disabled, removeButtonAriaLabel = _a.removeButtonAriaLabel, removeButtonIconProps = _a.removeButtonIconProps;
var onRenderItem = this.props.onRenderItem;
var _b = this.state, items = _b.items, selectedIndices = _b.selectedIndices;
return items.map(function (item, index) {
return onRenderItem({
item: item,
index: index,
key: item.key ? item.key : index,
selected: selectedIndices.indexOf(index) !== -1,
onRemoveItem: function () { return _this.removeItem(item); },
disabled: disabled,
onItemChange: _this.onItemChange,
removeButtonAriaLabel: removeButtonAriaLabel,
removeButtonIconProps: removeButtonIconProps,
});
});
};
BasePicker.prototype.resetFocus = function (index) {
var items = this.state.items;
if (items.length) {
// default to focusing the last item
index = index !== null && index !== void 0 ? index : items.length - 1;
var newEl = this.root.current &&
this.root.current.querySelectorAll('[data-selection-index] > button')[Math.min(index, items.length - 1)];
if (newEl) {
newEl.focus();
}
}
else {
if (this.input.current) {
this.input.current.focus();
}
}
};
BasePicker.prototype.onSuggestionSelect = function () {
if (this.suggestionStore.currentSuggestion) {
var currentValue = this.input.current ? this.input.current.value : '';
var itemValue = this._getTextFromItem(this.suggestionStore.currentSuggestion.item, currentValue);
this.setState({ suggestedDisplayValue: itemValue });
}
};
BasePicker.prototype.onSelectionChange = function () {
this.setState({
selectedIndices: this.selection.getSelectedIndices(),
});
};
BasePicker.prototype.updateSuggestions = function (suggestions) {
var _a;
var maxSuggestionsCount = (_a = this.props.pickerSuggestionsProps) === null || _a === void 0 ? void 0 : _a.resultsMaximumNumber;
this.suggestionStore.updateSuggestions(suggestions, 0, maxSuggestionsCount);
this.forceUpdate();
};
/**
* Only to be called when there is nothing in the input. Checks to see if the consumer has
* provided a function to resolve suggestions
*/
BasePicker.prototype.onEmptyInputFocus = function () {
var emptyResolveSuggestions = this.props.onEmptyResolveSuggestions
? this.props.onEmptyResolveSuggestions
: // eslint-disable-next-line @typescript-eslint/no-deprecated
this.props.onEmptyInputFocus;
// Only attempt to resolve suggestions if it exists
if (emptyResolveSuggestions) {
var suggestions = emptyResolveSuggestions(this.state.items);
this.updateSuggestionsList(suggestions);
this.setState({
isMostRecentlyUsedVisible: true,
suggestionsVisible: true,
moreSuggestionsAvailable: false,
});
}
};
BasePicker.prototype.updateValue = function (updatedValue) {
this._onResolveSuggestionsDebounced(updatedValue);
};
BasePicker.prototype.updateSuggestionsList = function (suggestions, updatedValue) {
var _this = this;
var _a;
// Check to see if the returned value is an array, if it is then just pass it into the next function .
// If the returned value is not an array then check to see if it's a promise or PromiseLike.
// If it is then resolve it asynchronously.
if (Array.isArray(suggestions)) {
this._updateAndResolveValue(updatedValue, suggestions);
}
else if (suggestions && suggestions.then) {
this.setState({
suggestionsLoading: true,
});
this._startLoadTimer();
// Clear suggestions
this.suggestionStore.updateSuggestions([]);
if (updatedValue !== undefined) {
this.setState({
suggestionsVisible: this._getShowSuggestions(),
});
}
else {
this.setState({
suggestionsVisible: this.input.current && this.input.current.inputElement === ((_a = (0, dom_1.getDocumentEx)(this.context)) === null || _a === void 0 ? void 0 : _a.activeElement),
});
}
// Ensure that the promise will only use the callback if it was the most recent one.
this.currentPromise = suggestions;
suggestions.then(function (newSuggestions) {
if (suggestions === _this.currentPromise) {
_this._updateAndResolveValue(updatedValue, newSuggestions);
}
});
}
};
BasePicker.prototype.resolveNewValue = function (updatedValue, suggestions) {
var _this = this;
this.updateSuggestions(suggestions);
var itemValue = undefined;
if (this.suggestionStore.currentSuggestion) {
itemValue = this._getTextFromItem(this.suggestionStore.currentSuggestion.item, updatedValue);
}
// Only set suggestionloading to false after there has been time for the new suggestions to flow
// to the suggestions list. This is to ensure that the suggestions are available before aria-activedescendant
// is set so that screen readers will read out the first selected option.
this.setState({
suggestedDisplayValue: itemValue,
suggestionsVisible: this._getShowSuggestions(),
}, function () { return _this.setState({ suggestionsLoading: false, suggestionsExtendedLoading: false }); });
};
BasePicker.prototype.onChange = function (items) {
if (this.props.onChange) {
this.props.onChange(items);
}
};
// This is protected because we may expect the backspace key to work differently in a different kind of picker.
// This lets the subclass override it and provide it's own onBackspace. For an example see the BasePickerListBelow
BasePicker.prototype.onBackspace = function (ev) {
if ((this.state.items.length && !this.input.current) ||
(this.input.current && !this.input.current.isValueSelected && this.input.current.cursorLocation === 0)) {
if (this.selection.getSelectedCount() > 0) {
this.removeItems(this.selection.getSelection());
}
else {
this.removeItem(this.state.items[this.state.items.length - 1]);
}
}
};
BasePicker.prototype.getActiveDescendant = function () {
var _a;
if (this.state.suggestionsLoading) {
return undefined;
}
var currentIndex = this.suggestionStore.currentIndex;
if (currentIndex < 0) {
// if the suggestions element has actions and the currentIndex does not point to a suggestion,
// return the action id
if ((_a = this.suggestionElement.current) === null || _a === void 0 ? void 0 : _a.hasSuggestedAction()) {
return 'sug-selectedAction';
}
// If there are no suggestions and no action suggested, then return the ID for the no results found.
if (this.suggestionStore.suggestions.length === 0) {
return 'sug-noResultsFound';
}
return undefined;
}
else {
return "sug-".concat(currentIndex);
}
};
/** @deprecated use renderCustomAlert instead */
BasePicker.prototype.getSuggestionsAlert = function (suggestionAlertClassName) {
if (suggestionAlertClassName === void 0) { suggestionAlertClassName = legacyStyles.screenReaderOnly; }
var currentIndex = this.suggestionStore.currentIndex;
if (this.props.enableSelectedSuggestionAlert) {
var selectedSuggestion = currentIndex > -1 ? this.suggestionStore.getSuggestionAtIndex(this.suggestionStore.currentIndex) : undefined;
var selectedSuggestionAlertText = selectedSuggestion ? selectedSuggestion.ariaLabel : undefined;
// keeping the id/className here for legacy support
return (React.createElement("div", { id: this._ariaMap.selectedSuggestionAlert, className: suggestionAlertClassName }, "".concat(selectedSuggestionAlertText, " ")));
}
};
BasePicker.prototype.renderCustomAlert = function (alertClassName) {
if (alertClassName === void 0) { alertClassName = legacyStyles.screenReaderOnly; }
var _a = this.props.suggestionRemovedText, suggestionRemovedText = _a === void 0 ? 'removed {0}' : _a;
var removedItemText = '';
if (this.state.selectionRemoved) {
var itemName = this._getTextFromItem(this.state.selectionRemoved, '');
removedItemText = (0, Utilities_1.format)(suggestionRemovedText, itemName);
}
return (React.createElement("div", { className: alertClassName, id: this._ariaMap.selectedSuggestionAlert, "aria-live": "assertive" },
// eslint-disable-next-line @typescript-eslint/no-deprecated
this.getSuggestionsAlert(alertClassName),
removedItemText));
};
// do not dismiss if the window resizes or scrolls within 100ms of opening
// this prevents the Android issue where pickers immediately dismiss on open, because the keyboard appears
BasePicker.prototype._preventDismissOnScrollOrResize = function (ev) {
if (this._overrideScrollDismiss && (ev.type === 'scroll' || ev.type === 'resize')) {
return true;
}
return false;
};
/** If suggestions are still loading after a predefined amount of time, set state to show user alert */
BasePicker.prototype._startLoadTimer = function () {
var _this = this;
this._async.setTimeout(function () {
if (_this.state.suggestionsLoading) {
_this.setState({ suggestionsExtendedLoading: true });
}
}, EXTENDED_LOAD_TIME);
};
/**
* Takes in the current updated value and either resolves it with the new suggestions
* or if updated value is undefined then it clears out currently suggested items
*/
BasePicker.prototype._updateAndResolveValue = function (updatedValue, newSuggestions) {
var _a;
if (updatedValue !== undefined) {
this.resolveNewValue(updatedValue, newSuggestions);
}
else {
var maxSuggestionsCount = (_a = this.props.pickerSuggestionsProps) === null || _a === void 0 ? void 0 : _a.resultsMaximumNumber;
this.suggestionStore.updateSuggestions(newSuggestions, -1, maxSuggestionsCount);
if (this.state.suggestionsLoading) {
this.setState({
suggestionsLoading: false,
suggestionsExtendedLoading: false,
});
}
}
};
BasePicker.prototype._getErrorMessage = function (items) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var errorMessage, err_1;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
if (this.props.errorMessage) {
return [2 /*return*/, this.props.errorMessage];
}
if (!this.props.onGetErrorMessage) return [3 /*break*/, 8];
_a.label = 1;
case 1:
_a.trys.push([1, 7, , 8]);
errorMessage = this.props.onGetErrorMessage(items);
if (!errorMessage) return [3 /*break*/, 5];
if (!errorMessage.then) return [3 /*break*/, 3];
return [4 /*yield*/, errorMessage];
case 2: return [2 /*return*/, _a.sent()];
case 3: return [2 /*return*/, errorMessage];
case 4: return [3 /*break*/, 6];
case 5: return [2 /*return*/, undefined];
case 6: return [3 /*break*/, 8];
case 7:
err_1 = _a.sent();
return [3 /*break*/, 8];
case 8: return [2 /*return*/];
}
});
});
};
BasePicker.prototype._updateErrorMessage = function (items) {
var _this = this;
var newErrorMessage;
this._getErrorMessage(items)
.then(function (errorMessage) {
newErrorMessage = errorMessage;
})
.catch(function () {
/* NO-OP */
})
.finally(function () {
if (_this._isMounted && newErrorMessage !== _this.state.errorMessage) {
_this.setState({ errorMessage: newErrorMessage });
}
});
};
/**
* Controls what happens whenever there is an action that impacts the selected items.
* If `selectedItems` is provided, this will act as a controlled component and it will not update its own state.
*/
BasePicker.prototype._updateSelectedItems = function (items) {
var _this = this;
if (this.props.selectedItems) {
// If the component is a controlled component then the controlling component will need to add or remove the items.
this.onChange(items);
}
else {
this.setState({ items: items }, function () {
_this._updateErrorMessage(items);
_this._onSelectedItemsUpdated(items);
});
}
};
BasePicker.prototype._onSelectedItemsUpdated = function (items) {
this.onChange(items);
};
/**
* Suggestions are normally shown after the user updates text and the text
* is non-empty, but also when the user clicks on the input element.
* @returns True if suggestions should be shown.
*/
BasePicker.prototype._getShowSuggestions = function () {
var _a;
var areSuggestionsVisible = this.input.current !== undefined &&
this.input.current !== null &&
this.input.current.inputElement === ((_a = (0, dom_1.getDocumentEx)(this.context)) === null || _a === void 0 ? void 0 : _a.activeElement) &&
this.input.current.value !== '';
return areSuggestionsVisible;
};
BasePicker.prototype._getTextFromItem = function (item, currentValue) {
if (this.props.getTextFromItem) {
return this.props.getTextFromItem(item, currentValue);
}
else {
return '';
}
};
BasePicker.contextType = react_window_provider_1.WindowContext;
return BasePicker;
}(React.Component));
exports.BasePicker = BasePicker;
var BasePickerListBelow = /** @class */ (function (_super) {
tslib_1.__extends(BasePickerListBelow, _super);
function BasePickerListBelow() {
return _super !== null && _super.apply(this, arguments) || this;
}
BasePickerListBelow.prototype.render = function () {
var _a, _b, _c, _d;
var _e = this.state, suggestedDisplayValue = _e.suggestedDisplayValue, isFocused = _e.isFocused, items = _e.items;
var _f = this.props, className = _f.className, inputProps = _f.inputProps, disabled = _f.disabled, selectionAriaLabel = _f.selectionAriaLabel, _g = _f.selectionRole, selectionRole = _g === void 0 ? 'list' : _g, theme = _f.theme, styles = _f.styles;
var suggestionsVisible = !!this.state.suggestionsVisible;
var suggestionsAvailable = suggestionsVisible ? this._ariaMap.suggestionList : undefined;
var hasError = !!((_a = this.state.errorMessage) !== null && _a !== void 0 ? _a : this.props.errorMessage);
// TODO
// Clean this up by leaving only the first part after removing support for SASS.
// Currently we can not remove the SASS styles from BasePicker class because it
// might be used by consumers who created custom pickers from extending from
// this base class and have not used the new 'styles' prop.
// We check for 'styles' prop which is going to be injected by the 'styled' HOC
// for every other already existing picker variant (PeoplePicker, TagPicker)
// so that we can use the CSS-in-JS styles. If the check fails (ex: custom picker),
// then we just use the old SASS styles instead.
var classNames = styles
? getClassNames(styles, {
theme: theme,
className: className,
isFocused: isFocused,
disabled: disabled,
hasErrorMessage: hasError,
inputClassName: inputProps && inputProps.className,
})
: {
root: (0, Utilities_1.css)('ms-BasePicker', legacyStyles.picker, className ? className : ''),
error: 'ms-BasePicker-error',
text: (0, Utilities_1.css)('ms-BasePicker-text', legacyStyles.pickerText, this.state.isFocused && legacyStyles.inputFocused, disabled && legacyStyles.inputDisabled),
itemsWrapper: legacyStyles.pickerItems,
input: (0, Utilities_1.css)('ms-BasePicker-input', legacyStyles.pickerInput, inputProps && inputProps.className),
screenReaderText: legacyStyles.screenReaderOnly,
};
var comboLabel = this.props['aria-label'] || (inputProps === null || inputProps === void 0 ? void 0 : inputProps['aria-label']);
var inputId = (_b = inputProps === null || inputProps === void 0 ? void 0 : inputProps.id) !== null && _b !== void 0 ? _b : this._ariaMap.combobox;
return (React.createElement("div", { ref: this.root, onBlur: this.onBlur, onFocus: this.onFocus },
this.renderLabel(inputId, (_c = classNames.subComponentStyles) === null || _c === void 0 ? void 0 : _c.label),
React.createElement("div", { className: classNames.root, onKeyDown: this.onKeyDown },
this.renderCustomAlert(classNames.screenReaderText),
React.createElement("span", { id: "".concat(this._ariaMap.selectedItems, "-label"), hidden: true }, selectionAriaLabel || comboLabel),
React.createElement("div", { className: classNames.text, "aria-owns": suggestionsAvailable },
React.createElement(index_2.Autofill, tslib_1.__assign({}, inputProps, { className: classNames.input, componentRef: this.input, onFocus: this.onInputFocus, onBlur: this.onInputBlur, onClick: this.onClick, onInputValueChange: this.onInputChange, suggestedDisplayValue: suggestedDisplayValue, "aria-activedescendant": suggestionsVisible ? this.getActiveDescendant() : undefined, "aria-controls": suggestionsAvailable, "aria-expanded": suggestionsVisible, "aria-haspopup": "listbox", "aria-label": comboLabel, "aria-describedby": this._getDescribedBy(items, hasError), role: "combobox", id: inputId, disabled: disabled,
// eslint-disable-next-line @typescript-eslint/no-deprecated
onInputChange: this.props.onInputChange })))),
this.renderSuggestions((_d = classNames.subComponentStyles) === null || _d === void 0 ? void 0 : _d.callout),
React.createElement(index_1.SelectionZone, { selection: this.selection, selectionMode: index_1.SelectionMode.single },
React.createElement("div", { id: this._ariaMap.selectedItems, className: "ms-BasePicker-selectedItems" // just a className hook without any styles applied to it.
, role: selectionRole, "aria-labelledby": "".concat(this._ariaMap.selectedItems, "-label") }, this.renderItems())),
this.renderError(classNames.error)));
};
BasePickerListBelow.prototype.onBackspace = function (ev) {
// override the existing backspace method to not do anything because the list items appear below.
};
return BasePickerListBelow;
}(BasePicker));
exports.BasePickerListBelow = BasePickerListBelow;
//# sourceMappingURL=BasePicker.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,7 @@
export declare const picker = "picker_94f06b16";
export declare const pickerText = "pickerText_94f06b16";
export declare const inputFocused = "inputFocused_94f06b16";
export declare const inputDisabled = "inputDisabled_94f06b16";
export declare const pickerInput = "pickerInput_94f06b16";
export declare const pickerItems = "pickerItems_94f06b16";
export declare const screenReaderOnly = "screenReaderOnly_94f06b16";
@@ -0,0 +1,14 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.screenReaderOnly = exports.pickerItems = exports.pickerInput = exports.inputDisabled = exports.inputFocused = exports.pickerText = exports.picker = void 0;
/* eslint-disable */
var load_themed_styles_1 = require("@microsoft/load-themed-styles");
(0, load_themed_styles_1.loadStyles)([{ "rawString": ".picker_94f06b16{position:relative}.pickerText_94f06b16{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-sizing:border-box;box-sizing:border-box;border:1px solid " }, { "theme": "neutralTertiary", "defaultValue": "#a19f9d" }, { "rawString": ";min-width:180px;min-height:30px}.pickerText_94f06b16:hover{border-color:" }, { "theme": "inputBorderHovered", "defaultValue": "#323130" }, { "rawString": "}.pickerText_94f06b16.inputFocused_94f06b16{position:relative;border-color:" }, { "theme": "inputFocusBorderAlt", "defaultValue": "#0078d4" }, { "rawString": "}.pickerText_94f06b16.inputFocused_94f06b16:after{pointer-events:none;content:\"\";position:absolute;left:-1px;top:-1px;bottom:-1px;right:-1px;border:2px solid " }, { "theme": "inputFocusBorderAlt", "defaultValue": "#0078d4" }, { "rawString": "}@media screen and (-ms-high-contrast:active),screen and (forced-colors:active){.pickerText_94f06b16.inputDisabled_94f06b16{position:relative;border-color:GrayText}.pickerText_94f06b16.inputDisabled_94f06b16:after{pointer-events:none;content:\"\";position:absolute;left:0;top:0;bottom:0;right:0;background-color:Window}}.pickerInput_94f06b16{height:34px;border:none;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;outline:0;padding:0 6px 0;-ms-flex-item-align:end;align-self:flex-end}.pickerItems_94f06b16{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;max-width:100%}.screenReaderOnly_94f06b16{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}" }]);
exports.picker = "picker_94f06b16";
exports.pickerText = "pickerText_94f06b16";
exports.inputFocused = "inputFocused_94f06b16";
exports.inputDisabled = "inputDisabled_94f06b16";
exports.pickerInput = "pickerInput_94f06b16";
exports.pickerItems = "pickerItems_94f06b16";
exports.screenReaderOnly = "screenReaderOnly_94f06b16";
//# sourceMappingURL=BasePicker.scss.js.map
@@ -0,0 +1 @@
{"version":3,"file":"BasePicker.scss.js","sourceRoot":"../src/","sources":["components/pickers/BasePicker.scss.ts"],"names":[],"mappings":";;;AAAA,oBAAoB;AACpB,oEAA2D;AAC3D,IAAA,+BAAU,EAAC,CAAC,EAAC,WAAW,EAAC,wRAAwR,EAAC,EAAC,EAAC,OAAO,EAAC,iBAAiB,EAAC,cAAc,EAAC,SAAS,EAAC,EAAC,EAAC,WAAW,EAAC,2EAA2E,EAAC,EAAC,EAAC,OAAO,EAAC,oBAAoB,EAAC,cAAc,EAAC,SAAS,EAAC,EAAC,EAAC,WAAW,EAAC,6EAA6E,EAAC,EAAC,EAAC,OAAO,EAAC,qBAAqB,EAAC,cAAc,EAAC,SAAS,EAAC,EAAC,EAAC,WAAW,EAAC,kKAAkK,EAAC,EAAC,EAAC,OAAO,EAAC,qBAAqB,EAAC,cAAc,EAAC,SAAS,EAAC,EAAC,EAAC,WAAW,EAAC,yuBAAyuB,EAAC,CAAC,CAAC,CAAC;AACtmD,QAAA,MAAM,GAAG,iBAAiB,CAAC;AAC3B,QAAA,UAAU,GAAG,qBAAqB,CAAC;AACnC,QAAA,YAAY,GAAG,uBAAuB,CAAC;AACvC,QAAA,aAAa,GAAG,wBAAwB,CAAC;AACzC,QAAA,WAAW,GAAG,sBAAsB,CAAC;AACrC,QAAA,WAAW,GAAG,sBAAsB,CAAC;AACrC,QAAA,gBAAgB,GAAG,2BAA2B,CAAC","sourcesContent":["/* eslint-disable */\nimport { loadStyles } from '@microsoft/load-themed-styles';\nloadStyles([{\"rawString\":\".picker_94f06b16{position:relative}.pickerText_94f06b16{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-sizing:border-box;box-sizing:border-box;border:1px solid \"},{\"theme\":\"neutralTertiary\",\"defaultValue\":\"#a19f9d\"},{\"rawString\":\";min-width:180px;min-height:30px}.pickerText_94f06b16:hover{border-color:\"},{\"theme\":\"inputBorderHovered\",\"defaultValue\":\"#323130\"},{\"rawString\":\"}.pickerText_94f06b16.inputFocused_94f06b16{position:relative;border-color:\"},{\"theme\":\"inputFocusBorderAlt\",\"defaultValue\":\"#0078d4\"},{\"rawString\":\"}.pickerText_94f06b16.inputFocused_94f06b16:after{pointer-events:none;content:\\\"\\\";position:absolute;left:-1px;top:-1px;bottom:-1px;right:-1px;border:2px solid \"},{\"theme\":\"inputFocusBorderAlt\",\"defaultValue\":\"#0078d4\"},{\"rawString\":\"}@media screen and (-ms-high-contrast:active),screen and (forced-colors:active){.pickerText_94f06b16.inputDisabled_94f06b16{position:relative;border-color:GrayText}.pickerText_94f06b16.inputDisabled_94f06b16:after{pointer-events:none;content:\\\"\\\";position:absolute;left:0;top:0;bottom:0;right:0;background-color:Window}}.pickerInput_94f06b16{height:34px;border:none;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;outline:0;padding:0 6px 0;-ms-flex-item-align:end;align-self:flex-end}.pickerItems_94f06b16{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;max-width:100%}.screenReaderOnly_94f06b16{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}\"}]);\nexport const picker = \"picker_94f06b16\";\nexport const pickerText = \"pickerText_94f06b16\";\nexport const inputFocused = \"inputFocused_94f06b16\";\nexport const inputDisabled = \"inputDisabled_94f06b16\";\nexport const pickerInput = \"pickerInput_94f06b16\";\nexport const pickerItems = \"pickerItems_94f06b16\";\nexport const screenReaderOnly = \"screenReaderOnly_94f06b16\";"]}
@@ -0,0 +1,2 @@
import type { IBasePickerStyleProps, IBasePickerStyles } from './BasePicker.types';
export declare function getStyles(props: IBasePickerStyleProps): IBasePickerStyles;
@@ -0,0 +1,166 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getStyles = getStyles;
var Styling_1 = require("../../Styling");
var GlobalClassNames = {
root: 'ms-BasePicker',
label: 'ms-BasePicker-label',
text: 'ms-BasePicker-text',
itemsWrapper: 'ms-BasePicker-itemsWrapper',
input: 'ms-BasePicker-input',
error: 'ms-BasePicker-error',
};
function getStyles(props) {
var _a, _b, _c;
var className = props.className, theme = props.theme, isFocused = props.isFocused, inputClassName = props.inputClassName, disabled = props.disabled, hasErrorMessage = props.hasErrorMessage;
if (!theme) {
throw new Error('theme is undefined or null in base BasePicker getStyles function.');
}
var semanticColors = theme.semanticColors, effects = theme.effects, fonts = theme.fonts;
var inputBorder = semanticColors.inputBorder, inputBorderHovered = semanticColors.inputBorderHovered, inputFocusBorderAlt = semanticColors.inputFocusBorderAlt;
var classNames = (0, Styling_1.getGlobalClassNames)(GlobalClassNames, theme);
// placeholder style constants
var placeholderStyles = [
fonts.medium,
{
color: semanticColors.inputPlaceholderText,
opacity: 1,
selectors: (_a = {},
_a[Styling_1.HighContrastSelector] = {
color: 'GrayText',
},
_a),
},
];
var disabledPlaceholderStyles = {
color: semanticColors.disabledText,
selectors: (_b = {},
_b[Styling_1.HighContrastSelector] = {
color: 'GrayText',
},
_b),
};
// The following lines are to create a semi-transparent color overlay for the disabled state with designer's approval.
// @todo: investigate the performance cost of the calculation below and apply if negligible.
// Replacing with a static color for now.
// const rgbColor: IRGB | undefined = cssColor(palette.neutralQuaternaryAlt);
// const disabledOverlayColor = rgbColor ? `rgba(${rgbColor.r}, ${rgbColor.g}, ${rgbColor.b}, 0.29)` : 'transparent';
var disabledOverlayColor = 'rgba(218, 218, 218, 0.29)';
var focusColor = isFocused && !disabled && (hasErrorMessage ? semanticColors.errorText : inputFocusBorderAlt);
return {
root: [classNames.root, className, { position: 'relative' }],
error: [
classNames.error,
{
fontSize: 12,
fontWeight: 400,
color: semanticColors.errorText,
margin: 0,
paddingTop: 5,
display: hasErrorMessage ? 'flex' : 'none',
alignItems: 'center',
},
],
text: [
classNames.text,
{
display: 'flex',
position: 'relative',
flexWrap: 'wrap',
alignItems: 'center',
boxSizing: 'border-box',
minWidth: 180,
minHeight: 30,
border: "1px solid ".concat(inputBorder),
borderRadius: effects.roundedCorner2,
},
!isFocused &&
!disabled && {
selectors: {
':hover': {
borderColor: inputBorderHovered,
},
},
},
focusColor && (0, Styling_1.getInputFocusStyle)(focusColor, effects.roundedCorner2),
disabled && {
borderColor: disabledOverlayColor,
selectors: (_c = {
':after': {
content: '""',
position: 'absolute',
top: 0,
right: 0,
bottom: 0,
left: 0,
background: disabledOverlayColor,
}
},
_c[Styling_1.HighContrastSelector] = {
borderColor: 'GrayText',
selectors: {
':after': {
background: 'none',
},
},
},
_c),
},
hasErrorMessage && {
borderColor: semanticColors.errorText,
selectors: {
':hover': {
borderColor: semanticColors.errorText,
},
},
},
],
itemsWrapper: [
classNames.itemsWrapper,
{
display: 'flex',
flexWrap: 'wrap',
maxWidth: '100%',
},
],
input: [
classNames.input,
fonts.medium,
{
height: 30,
border: 'none',
flexGrow: 1,
outline: 'none',
padding: '0 6px 0',
alignSelf: 'flex-end',
borderRadius: effects.roundedCorner2,
backgroundColor: 'transparent',
color: semanticColors.inputText,
selectors: {
'::-ms-clear': {
display: 'none',
},
'&:placeholder-shown': {
textOverflow: 'ellipsis',
},
},
},
(0, Styling_1.getPlaceholderStyles)(placeholderStyles),
disabled && (0, Styling_1.getPlaceholderStyles)(disabledPlaceholderStyles),
inputClassName,
],
screenReaderText: Styling_1.hiddenContentStyle,
subComponentStyles: {
label: {},
callout: {
// Picker suggestions already manage overflow and scrolling items into view
// for this to work at all screen sizes, we need Callout to not also have overflow
calloutMain: {
overflow: 'unset',
maxHeight: '100%',
},
},
},
};
}
//# sourceMappingURL=BasePicker.styles.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,322 @@
import * as React from 'react';
import { Autofill } from '../../Autofill';
import type { IPickerItemProps } from './PickerItem.types';
import type { IReactProps, IRefObject, IStyleFunctionOrObject } from '../../Utilities';
import type { ISuggestionModel, ISuggestionsProps } from './Suggestions/Suggestions.types';
import type { ICalloutProps, ICalloutContentStyleProps, ICalloutContentStyles } from '../../Callout';
import type { ITheme, IStyle } from '../../Styling';
import type { ISuggestionItemProps } from '../pickers/Suggestions/SuggestionsItem.types';
import { IIconProps } from '../Icon/Icon.types';
import { ILabelStyleProps, ILabelStyles } from '../Label/Label.types';
import type { JSXElement } from '@fluentui/utilities';
/**
* BasePicker component.
* {@docCategory Pickers}
*/
export interface IBasePicker<T> {
/** Gets the current value of the input. */
items: T[] | undefined;
/** Sets focus to the focus zone. */
focus: () => void;
/** Set focus to the input */
focusInput: () => void;
/**
* When called, will take the currently selected suggestion and complete it.
* If called with forceComplete true, it will attempt to force the current suggestion
* to complete, must provide both createGenericSuggestion, so the text can be turned into
* an object in the right shape, and onValidateInput, so the object knows if it's correct or not.
*/
completeSuggestion: (forceComplete?: boolean) => void;
}
/**
* Type T is the type of the item that is displayed
* and searched for by the picker. For example, if the picker is
* displaying persona's then type T could either be of Persona or IPersona props
* {@docCategory Pickers}
*/
export interface IBasePickerProps<T> extends IReactProps<any> {
/**
* Optional callback to access the IBasePicker interface. Use this instead of ref for accessing
* the public methods and properties of the component.
*/
componentRef?: IRefObject<IBasePicker<T>>;
/**
* Descriptive label for the field.
*/
label?: string;
/**
* Function that specifies how the selected item will appear.
*/
onRenderItem?: (props: IPickerItemProps<T>) => JSXElement;
/**
* Function that specifies how an individual suggestion item will appear.
*/
onRenderSuggestionsItem?: (props: T, itemProps: ISuggestionItemProps<T>) => JSXElement;
/**
* A callback for what should happen when a person types text into the input.
* Returns the already selected items so the resolver can filter them out.
* If used in conjunction with resolveDelay this will only kick off after the delay throttle.
*/
onResolveSuggestions: (filter: string, selectedItems?: T[]) => T[] | PromiseLike<T[]>;
/**
* The delay time in ms before resolving suggestions, which is kicked off when input has been changed.
* e.g. If a second input change happens within the resolveDelay time, the timer will start over.
* Only until after the timer completes will onResolveSuggestions be called.
*/
resolveDelay?: number;
/**
* A callback for what should happen when a user clicks within the input area.
* @deprecated Please use `onEmptyResolveSuggestions` instead, as the suggestions aren't about
* setting focus as they are about resolving suggestions when there is no input.
*/
onEmptyInputFocus?: (selectedItems?: T[]) => T[] | PromiseLike<T[]>;
/**
* A callback for what should happen when suggestions are shown without
* input provided.
* Returns the already selected items so the resolver can filter them out.
* If used in conjunction with resolveDelay this will only kick off after the delay throttle.
*/
onEmptyResolveSuggestions?: (selectedItems?: T[]) => T[] | PromiseLike<T[]>;
/**
* Initial items that have already been selected and should appear in the people picker.
*/
defaultSelectedItems?: T[];
/**
* A callback for when the selected list of items changes.
*/
onChange?: (items?: T[]) => void;
/**
* A callback for when the user put focus on the picker
* @deprecated Use `inputProps.onFocus` instead
*/
onFocus?: React.FocusEventHandler<HTMLInputElement | Autofill>;
/**
* A callback for when the user moves the focus away from the picker
*/
onBlur?: React.FocusEventHandler<HTMLInputElement | Autofill>;
/**
* A callback to get text from an item. Used to autofill text in the pickers.
*/
getTextFromItem?: (item: T, currentValue?: string) => string;
/**
* A callback that gets the rest of the results when a user clicks get more results.
*/
onGetMoreResults?: (filter: string, selectedItems?: T[]) => T[] | PromiseLike<T[]>;
/**
* ClassName for the picker.
*/
className?: string;
/**
* The properties that will get passed to the Suggestions component.
*/
pickerSuggestionsProps?: IBasePickerSuggestionsProps;
/**
* The properties that will get passed to the Callout component.
*/
pickerCalloutProps?: ICalloutProps;
/**
* AutoFill input native props
* @defaultvalue undefined
*/
inputProps?: IInputProps;
/**
* Static error message displayed below the selection zone of the field. Use `onGetErrorMessage` to dynamically
* change the error message displayed (if any) based on the current value. `errorMessage` and
* `onGetErrorMessage` are mutually exclusive (`errorMessage` takes precedence).
*/
errorMessage?: string | JSXElement;
/**
* Function used to determine whether the selected items are valid and get an error message if not.
* Mutually exclusive with the static string `errorMessage` (it will take precedence over this).
*
* When it returns `string | JSXElement`:
* - If valid, it returns empty string.
* - If invalid, it returns the error message and the text field will
* show a red border and show an error message below the text field.
*
* When it returns `Promise<string | JSXElement>`:
* - The resolved value is displayed as the error message.
* - If rejected, the value is thrown away.
*/
onGetErrorMessage?: (items: T[]) => string | JSXElement | PromiseLike<string | JSXElement> | undefined;
/**
* A callback for when an item is removed from the suggestion list
*/
onRemoveSuggestion?: (item: T) => void;
/**
* A function used to validate if raw text entered into the well can be added into the selected items list
*/
onValidateInput?: (input: string) => ValidationState;
/**
* The text to display while searching for more results in a limited suggestions list
*/
searchingText?: ((props: {
input: string;
}) => string) | string;
/**
* Flag for disabling the picker.
* @defaultvalue false
*/
disabled?: boolean;
/**
* Whether or not the field is required.
* @defaultvalue false
*/
required?: boolean;
/**
* Restrict the amount of selectable items.
* @defaultvalue undefined
*/
itemLimit?: number;
/**
* Function that specifies how arbitrary text entered into the well is handled.
*/
createGenericItem?: (input: string, ValidationState: ValidationState) => ISuggestionModel<T> | T;
/**
* Aria label for the "X" button in the selected item component.
* @defaultvalue ''
*/
removeButtonAriaLabel?: string;
/**
* The text that will be announced when a suggestion is removed. A default value is only provided for English.
* @default 'removed \{0\}'
*/
suggestionRemovedText?: string;
/**
* Optional aria-label that will be placed on the element that has the role "combobox"
* attached. Additionally aria-labelled by will get added to the supporting input element contained
* with in the combobox container
*/
['aria-label']?: string;
/**
* A callback to process a selection after the user selects something from the picker. If the callback returns null,
* the item will not be added to the picker.
*/
onItemSelected?: (selectedItem?: T) => T | PromiseLike<T> | null;
/**
* The items that the base picker should currently display as selected.
* If this is provided then the picker will act as a controlled component.
*/
selectedItems?: T[];
/**
* Aria label for the displayed selection. A good value would be something like "Selected Contacts".
* @defaultvalue ''
*/
selectionAriaLabel?: string;
/**
* Override the role used for the element containing selected items.
* Update this if onRenderItem does not return elements with role="listitem".
* A good alternative would be 'group'.
* @defaultvalue 'list'
*/
selectionRole?: string;
/**
* A callback used to modify the input string.
*/
onInputChange?: (input: string) => string;
/**
* A callback to override the default behavior of adding the selected suggestion on dismiss. If it returns true or
* nothing, the selected item will be added on dismiss. If false, the selected item will not be added on dismiss.
*
*/
onDismiss?: (ev?: any, selectedItem?: T) => boolean | void;
/**
* Adds an additional alert for the currently selected suggestion. This prop should be set to true for IE11 and below,
* as it enables proper screen reader behavior for each suggestion (since aria-activedescendant does not work
* with IE11). It should not be set for modern browsers (Edge, Chrome).
* @defaultvalue false
*/
enableSelectedSuggestionAlert?: boolean;
/**
* Call to provide customized styling that will layer on top of the variant rules.
*/
styles?: IStyleFunctionOrObject<IBasePickerStyleProps, IBasePickerStyles>;
/**
* Theme provided by styled() function.
*/
theme?: ITheme;
/**
* Props for the icon used in the item's remove button.
* @defaultvalue `{ iconName:'Cancel' }`
*/
removeButtonIconProps?: IIconProps;
}
/**
* Subset of picker options that may be legally passed through a picker to its
* internal Suggestions component.
* {@docCategory Pickers}
*/
export interface IBasePickerSuggestionsProps<T = any> extends Pick<ISuggestionsProps<T>, 'onRenderNoResultFound' | 'suggestionsHeaderText' | 'mostRecentlyUsedHeaderText' | 'noResultsFoundText' | 'className' | 'suggestionsClassName' | 'suggestionsItemClassName' | 'searchForMoreIcon' | 'searchForMoreText' | 'forceResolveText' | 'loadingText' | 'searchingText' | 'resultsFooterFull' | 'resultsFooter' | 'resultsMaximumNumber' | 'showRemoveButtons' | 'suggestionsAvailableAlertText' | 'suggestionsContainerAriaLabel' | 'showForceResolve' | 'removeButtonIconProps'> {
}
/**
* Validation state of the user's input.
* {@docCategory Pickers}
*/
export declare enum ValidationState {
/** User input is valid. */
valid = 0,
/** User input could be valid or invalid, its state is not known yet. */
warning = 1,
/** User input is invalid. */
invalid = 2
}
/**
* Pickers' input props interface
* {@docCategory Pickers}
*/
export interface IInputProps extends React.InputHTMLAttributes<HTMLInputElement> {
/**
* Screen reader label to apply to an input element.
*/
'aria-label'?: string;
/**
* The default value to be visible when the autofill first created.
* This is different than placeholder text because the placeholder text will disappear and re-appear. This
* text persists until deleted or changed.
*/
defaultVisibleValue?: string;
}
/**
* The props needed to construct styles.
* {@docCategory Pickers}
*/
export type IBasePickerStyleProps = Pick<IBasePickerProps<any>, 'theme' | 'className' | 'disabled'> & {
/** Whether the element has an error message or not. */
hasErrorMessage: boolean;
/** Whether text style area is focused */
isFocused?: boolean;
/** Optional pickerInput className */
inputClassName?: string;
};
/**
* {@docCategory Pickers}
*/
export interface IBasePickerSubComponentStyles {
/** Styling for Label child component. */
label: IStyleFunctionOrObject<ILabelStyleProps, ILabelStyles>;
/** Styling for Callout child component. */
callout: IStyleFunctionOrObject<ICalloutContentStyleProps, ICalloutContentStyles>;
}
/**
* Represents the stylable areas of the control.
* {@docCategory Pickers}
*/
export interface IBasePickerStyles {
/** Root element of any picker extending from BasePicker (wraps all the elements). */
root: IStyle;
/** Refers fo the error message element. */
error: IStyle;
/**
* Refers to the elements already selected (picked) wrapped by `itemsWrapper` along with the input to type
* a new selection.
*/
text: IStyle;
/** Styling for subcomponents. */
subComponentStyles: IBasePickerSubComponentStyles;
/** Refers to the items already selected (picked). */
itemsWrapper: IStyle;
/** Refers to the input were to type new selections (picks). */
input: IStyle;
/** Refers to helper element used for accessibility tools (hidden from view on screen). */
screenReaderText: IStyle;
}
@@ -0,0 +1,17 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ValidationState = void 0;
/**
* Validation state of the user's input.
* {@docCategory Pickers}
*/
var ValidationState;
(function (ValidationState) {
/** User input is valid. */
ValidationState[ValidationState["valid"] = 0] = "valid";
/** User input could be valid or invalid, its state is not known yet. */
ValidationState[ValidationState["warning"] = 1] = "warning";
/** User input is invalid. */
ValidationState[ValidationState["invalid"] = 2] = "invalid";
})(ValidationState || (exports.ValidationState = ValidationState = {}));
//# sourceMappingURL=BasePicker.types.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,76 @@
import * as React from 'react';
import { BasePicker, BasePickerListBelow } from '../BasePicker';
import { ValidationState } from '../BasePicker.types';
import type { IBasePickerProps, IBasePickerSuggestionsProps } from '../BasePicker.types';
import type { IPersonaProps } from '../../../Persona';
import type { IPeoplePickerItemSelectedProps } from './PeoplePickerItems/PeoplePickerItem.types';
import type { JSXElement } from '@fluentui/utilities';
/**
* PeoplePicker props interface which renders Personas as items.
* {@docCategory PeoplePicker}
* */
export interface IPeoplePickerProps extends IBasePickerProps<IPersonaProps> {
}
/**
* {@docCategory PeoplePicker}
*/
export declare class BasePeoplePicker extends BasePicker<IPersonaProps, IPeoplePickerProps> {
}
/**
* {@docCategory PeoplePicker}
*/
export declare class MemberListPeoplePicker extends BasePickerListBelow<IPersonaProps, IPeoplePickerProps> {
}
/**
* Standard People Picker.
* {@docCategory PeoplePicker}
*/
export declare class NormalPeoplePickerBase extends BasePeoplePicker {
/** Default props for NormalPeoplePicker. */
static defaultProps: {
onRenderItem: (props: IPeoplePickerItemSelectedProps) => JSXElement;
onRenderSuggestionsItem: (personaProps: IPersonaProps, suggestionsProps?: IBasePickerSuggestionsProps) => JSXElement;
createGenericItem: typeof createGenericItem;
};
}
/**
* Compact layout. It uses personas without secondary text when displaying search results.
* {@docCategory PeoplePicker}
*/
export declare class CompactPeoplePickerBase extends BasePeoplePicker {
/** Default props for CompactPeoplePicker. */
static defaultProps: {
onRenderItem: (props: IPeoplePickerItemSelectedProps) => JSXElement;
onRenderSuggestionsItem: (personaProps: IPersonaProps, suggestionsProps?: IBasePickerSuggestionsProps) => JSXElement;
createGenericItem: typeof createGenericItem;
};
}
/**
* MemberList layout. The selected people show up below the search box.
* {@docCategory PeoplePicker}
*/
export declare class ListPeoplePickerBase extends MemberListPeoplePicker {
/** Default props for ListPeoplePicker. */
static defaultProps: {
onRenderItem: (props: IPeoplePickerItemSelectedProps) => JSXElement;
onRenderSuggestionsItem: (personaProps: IPersonaProps, suggestionsProps?: IBasePickerSuggestionsProps) => JSXElement;
createGenericItem: typeof createGenericItem;
};
}
/**
* {@docCategory PeoplePicker}
*/
export interface IGenericItem {
primaryText: string;
imageInitials: string;
ValidationState: ValidationState;
}
/**
* {@docCategory PeoplePicker}
*/
export declare function createGenericItem(name: string, currentValidationState: ValidationState): IGenericItem & {
key: React.Key;
};
export declare const NormalPeoplePicker: React.FunctionComponent<React.PropsWithChildren<React.PropsWithChildren<IPeoplePickerProps>>>;
export declare const CompactPeoplePicker: React.FunctionComponent<React.PropsWithChildren<React.PropsWithChildren<IPeoplePickerProps>>>;
export declare const ListPeoplePicker: React.FunctionComponent<React.PropsWithChildren<React.PropsWithChildren<IPeoplePickerProps>>>;
@@ -0,0 +1,113 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ListPeoplePicker = exports.CompactPeoplePicker = exports.NormalPeoplePicker = exports.ListPeoplePickerBase = exports.CompactPeoplePickerBase = exports.NormalPeoplePickerBase = exports.MemberListPeoplePicker = exports.BasePeoplePicker = void 0;
exports.createGenericItem = createGenericItem;
var tslib_1 = require("tslib");
var React = require("react");
var Utilities_1 = require("../../../Utilities");
var BasePicker_1 = require("../BasePicker");
var BasePicker_types_1 = require("../BasePicker.types");
var PeoplePickerItem_1 = require("./PeoplePickerItems/PeoplePickerItem");
var PeoplePickerItemSuggestion_1 = require("./PeoplePickerItems/PeoplePickerItemSuggestion");
var BasePicker_styles_1 = require("../BasePicker.styles");
/**
* {@docCategory PeoplePicker}
*/
var BasePeoplePicker = /** @class */ (function (_super) {
tslib_1.__extends(BasePeoplePicker, _super);
function BasePeoplePicker() {
return _super !== null && _super.apply(this, arguments) || this;
}
return BasePeoplePicker;
}(BasePicker_1.BasePicker));
exports.BasePeoplePicker = BasePeoplePicker;
/**
* {@docCategory PeoplePicker}
*/
var MemberListPeoplePicker = /** @class */ (function (_super) {
tslib_1.__extends(MemberListPeoplePicker, _super);
function MemberListPeoplePicker() {
return _super !== null && _super.apply(this, arguments) || this;
}
return MemberListPeoplePicker;
}(BasePicker_1.BasePickerListBelow));
exports.MemberListPeoplePicker = MemberListPeoplePicker;
/**
* Standard People Picker.
* {@docCategory PeoplePicker}
*/
var NormalPeoplePickerBase = /** @class */ (function (_super) {
tslib_1.__extends(NormalPeoplePickerBase, _super);
function NormalPeoplePickerBase() {
return _super !== null && _super.apply(this, arguments) || this;
}
/** Default props for NormalPeoplePicker. */
NormalPeoplePickerBase.defaultProps = {
onRenderItem: function (props) { return React.createElement(PeoplePickerItem_1.PeoplePickerItem, tslib_1.__assign({}, props)); },
onRenderSuggestionsItem: function (personaProps, suggestionsProps) { return React.createElement(PeoplePickerItemSuggestion_1.PeoplePickerItemSuggestion, { personaProps: personaProps, suggestionsProps: suggestionsProps }); },
createGenericItem: createGenericItem,
};
return NormalPeoplePickerBase;
}(BasePeoplePicker));
exports.NormalPeoplePickerBase = NormalPeoplePickerBase;
/**
* Compact layout. It uses personas without secondary text when displaying search results.
* {@docCategory PeoplePicker}
*/
var CompactPeoplePickerBase = /** @class */ (function (_super) {
tslib_1.__extends(CompactPeoplePickerBase, _super);
function CompactPeoplePickerBase() {
return _super !== null && _super.apply(this, arguments) || this;
}
/** Default props for CompactPeoplePicker. */
CompactPeoplePickerBase.defaultProps = {
onRenderItem: function (props) { return React.createElement(PeoplePickerItem_1.PeoplePickerItem, tslib_1.__assign({}, props)); },
onRenderSuggestionsItem: function (personaProps, suggestionsProps) { return (React.createElement(PeoplePickerItemSuggestion_1.PeoplePickerItemSuggestion, { personaProps: personaProps, suggestionsProps: suggestionsProps, compact: true })); },
createGenericItem: createGenericItem,
};
return CompactPeoplePickerBase;
}(BasePeoplePicker));
exports.CompactPeoplePickerBase = CompactPeoplePickerBase;
/**
* MemberList layout. The selected people show up below the search box.
* {@docCategory PeoplePicker}
*/
var ListPeoplePickerBase = /** @class */ (function (_super) {
tslib_1.__extends(ListPeoplePickerBase, _super);
function ListPeoplePickerBase() {
return _super !== null && _super.apply(this, arguments) || this;
}
/** Default props for ListPeoplePicker. */
ListPeoplePickerBase.defaultProps = {
onRenderItem: function (props) { return React.createElement(PeoplePickerItem_1.PeoplePickerItem, tslib_1.__assign({}, props)); },
onRenderSuggestionsItem: function (personaProps, suggestionsProps) { return React.createElement(PeoplePickerItemSuggestion_1.PeoplePickerItemSuggestion, { personaProps: personaProps, suggestionsProps: suggestionsProps }); },
createGenericItem: createGenericItem,
};
return ListPeoplePickerBase;
}(MemberListPeoplePicker));
exports.ListPeoplePickerBase = ListPeoplePickerBase;
/**
* {@docCategory PeoplePicker}
*/
function createGenericItem(name, currentValidationState) {
var personaToConvert = {
key: name,
primaryText: name,
imageInitials: '!',
ValidationState: currentValidationState,
};
if (currentValidationState !== BasePicker_types_1.ValidationState.warning) {
personaToConvert.imageInitials = (0, Utilities_1.getInitials)(name, (0, Utilities_1.getRTL)());
}
return personaToConvert;
}
exports.NormalPeoplePicker = (0, Utilities_1.styled)(NormalPeoplePickerBase, BasePicker_styles_1.getStyles, undefined, {
scope: 'NormalPeoplePicker',
});
exports.CompactPeoplePicker = (0, Utilities_1.styled)(CompactPeoplePickerBase, BasePicker_styles_1.getStyles, undefined, {
scope: 'CompactPeoplePicker',
});
exports.ListPeoplePicker = (0, Utilities_1.styled)(ListPeoplePickerBase, BasePicker_styles_1.getStyles, undefined, {
scope: 'ListPeoplePickerBase',
});
//# sourceMappingURL=PeoplePicker.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,5 @@
import * as React from 'react';
import type { IPeoplePickerItemSelectedProps } from './PeoplePickerItem.types';
import type { JSXElement } from '@fluentui/utilities';
export declare const PeoplePickerItemBase: (props: IPeoplePickerItemSelectedProps) => JSXElement;
export declare const PeoplePickerItem: React.FunctionComponent<React.PropsWithChildren<React.PropsWithChildren<IPeoplePickerItemSelectedProps>>>;
@@ -0,0 +1,40 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PeoplePickerItem = exports.PeoplePickerItemBase = void 0;
var tslib_1 = require("tslib");
var React = require("react");
var Utilities_1 = require("../../../../Utilities");
var Persona_1 = require("../../../../Persona");
var Button_1 = require("../../../../Button");
var BasePicker_types_1 = require("../../BasePicker.types");
var PeoplePickerItem_styles_1 = require("./PeoplePickerItem.styles");
var getClassNames = (0, Utilities_1.classNamesFunction)();
var PeoplePickerItemBase = function (props) {
var item = props.item, onRemoveItem = props.onRemoveItem, index = props.index, selected = props.selected, removeButtonAriaLabel = props.removeButtonAriaLabel, styles = props.styles, theme = props.theme, className = props.className, disabled = props.disabled, removeButtonIconProps = props.removeButtonIconProps;
var buttonRef = React.createRef();
var handleClick = function () {
var _a;
(_a = buttonRef.current) === null || _a === void 0 ? void 0 : _a.focus();
};
var itemId = (0, Utilities_1.getId)();
var classNames = getClassNames(styles, {
theme: theme,
className: className,
selected: selected,
disabled: disabled,
invalid: item.ValidationState === BasePicker_types_1.ValidationState.warning,
});
var personaStyles = classNames.subComponentStyles
? classNames.subComponentStyles.persona
: undefined;
var personaCoinStyles = classNames.subComponentStyles
? classNames.subComponentStyles.personaCoin
: undefined;
return (React.createElement("div", { "data-selection-index": index, className: classNames.root, role: 'listitem', key: index, onClick: handleClick },
React.createElement("div", { className: classNames.itemContent, id: 'selectedItemPersona-' + itemId },
React.createElement(Persona_1.Persona, tslib_1.__assign({ size: Persona_1.PersonaSize.size24, styles: personaStyles, coinProps: { styles: personaCoinStyles } }, item))),
React.createElement(Button_1.IconButton, { componentRef: buttonRef, id: itemId, onClick: onRemoveItem, disabled: disabled, iconProps: removeButtonIconProps !== null && removeButtonIconProps !== void 0 ? removeButtonIconProps : { iconName: 'Cancel' }, styles: { icon: { fontSize: '12px' } }, className: classNames.removeButton, ariaLabel: removeButtonAriaLabel, "aria-labelledby": "".concat(itemId, " selectedItemPersona-").concat(itemId) })));
};
exports.PeoplePickerItemBase = PeoplePickerItemBase;
exports.PeoplePickerItem = (0, Utilities_1.styled)(exports.PeoplePickerItemBase, PeoplePickerItem_styles_1.getStyles, undefined, { scope: 'PeoplePickerItem' });
//# sourceMappingURL=PeoplePickerItem.js.map
@@ -0,0 +1 @@
{"version":3,"file":"PeoplePickerItem.js","sourceRoot":"../src/","sources":["components/pickers/PeoplePicker/PeoplePickerItems/PeoplePickerItem.tsx"],"names":[],"mappings":";;;;AAAA,6BAA+B;AAE/B,mDAA0E;AAC1E,+CAA2D;AAC3D,6CAAyD;AACzD,2DAAyD;AACzD,qEAAsD;AAgBtD,IAAM,aAAa,GAAG,IAAA,8BAAkB,GAAwE,CAAC;AAE1G,IAAM,oBAAoB,GAAG,UAAC,KAAqC;IAEtE,IAAA,IAAI,GAUF,KAAK,KAVH,EACJ,YAAY,GASV,KAAK,aATK,EACZ,KAAK,GAQH,KAAK,MARF,EACL,QAAQ,GAON,KAAK,SAPC,EACR,qBAAqB,GAMnB,KAAK,sBANc,EACrB,MAAM,GAKJ,KAAK,OALD,EACN,KAAK,GAIH,KAAK,MAJF,EACL,SAAS,GAGP,KAAK,UAHE,EACT,QAAQ,GAEN,KAAK,SAFC,EACR,qBAAqB,GACnB,KAAK,sBADc,CACb;IAEV,IAAM,SAAS,GAAG,KAAK,CAAC,SAAS,EAAW,CAAC;IAE7C,IAAM,WAAW,GAA4C;;QAC3D,MAAA,SAAS,CAAC,OAAO,0CAAE,KAAK,EAAE,CAAC;IAC7B,CAAC,CAAC;IAEF,IAAM,MAAM,GAAG,IAAA,iBAAK,GAAE,CAAC;IAEvB,IAAM,UAAU,GAAG,aAAa,CAAC,MAAM,EAAE;QACvC,KAAK,EAAE,KAAM;QACb,SAAS,WAAA;QACT,QAAQ,UAAA;QACR,QAAQ,UAAA;QACR,OAAO,EAAE,IAAI,CAAC,eAAe,KAAK,kCAAe,CAAC,OAAO;KAC1D,CAAC,CAAC;IAEH,IAAM,aAAa,GAAG,UAAU,CAAC,kBAAkB;QACjD,CAAC,CAAE,UAAU,CAAC,kBAAkB,CAAC,OAAsE;QACvG,CAAC,CAAC,SAAS,CAAC;IAEd,IAAM,iBAAiB,GAAG,UAAU,CAAC,kBAAkB;QACrD,CAAC,CAAE,UAAU,CAAC,kBAAkB,CAAC,WAAkF;QACnH,CAAC,CAAC,SAAS,CAAC;IAEd,OAAO,CACL,qDAA2B,KAAK,EAAE,SAAS,EAAE,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW;QAC9G,6BAAK,SAAS,EAAE,UAAU,CAAC,WAAW,EAAE,EAAE,EAAE,sBAAsB,GAAG,MAAM;YACzE,oBAAC,iBAAO,qBAAC,IAAI,EAAE,qBAAW,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,iBAAiB,EAAE,IAAM,IAAI,EAAI,CAC5G;QACN,oBAAC,mBAAU,IACT,YAAY,EAAE,SAAS,EACvB,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,YAAY,EACrB,QAAQ,EAAE,QAAQ,EAClB,SAAS,EAAE,qBAAqB,aAArB,qBAAqB,cAArB,qBAAqB,GAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAC1D,MAAM,EAAE,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EACtC,SAAS,EAAE,UAAU,CAAC,YAAY,EAClC,SAAS,EAAE,qBAAqB,qBACf,UAAG,MAAM,kCAAwB,MAAM,CAAE,GAC1D,CACE,CACP,CAAC;AACJ,CAAC,CAAC;AAxDW,QAAA,oBAAoB,wBAwD/B;AAEW,QAAA,gBAAgB,GAAG,IAAA,kBAAM,EAIpC,4BAAoB,EAAE,mCAAS,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,kBAAkB,EAAE,CAAC,CAAC","sourcesContent":["import * as React from 'react';\n\nimport { getId, classNamesFunction, styled } from '../../../../Utilities';\nimport { Persona, PersonaSize } from '../../../../Persona';\nimport { IconButton, IButton } from '../../../../Button';\nimport { ValidationState } from '../../BasePicker.types';\nimport { getStyles } from './PeoplePickerItem.styles';\nimport type { IStyleFunctionOrObject } from '../../../../Utilities';\nimport type {\n IPersonaStyleProps,\n IPersonaStyles,\n IPersonaCoinStyleProps,\n IPersonaCoinStyles,\n} from '../../../../Persona';\nimport type {\n IPeoplePickerItemSelectedProps,\n IPeoplePickerItemSelectedStyleProps,\n IPeoplePickerItemSelectedStyles,\n} from './PeoplePickerItem.types';\n\nimport type { JSXElement } from '@fluentui/utilities';\n\nconst getClassNames = classNamesFunction<IPeoplePickerItemSelectedStyleProps, IPeoplePickerItemSelectedStyles>();\n\nexport const PeoplePickerItemBase = (props: IPeoplePickerItemSelectedProps): JSXElement => {\n const {\n item,\n onRemoveItem,\n index,\n selected,\n removeButtonAriaLabel,\n styles,\n theme,\n className,\n disabled,\n removeButtonIconProps,\n } = props;\n\n const buttonRef = React.createRef<IButton>();\n\n const handleClick: React.MouseEventHandler<HTMLDivElement> = () => {\n buttonRef.current?.focus();\n };\n\n const itemId = getId();\n\n const classNames = getClassNames(styles, {\n theme: theme!,\n className,\n selected,\n disabled,\n invalid: item.ValidationState === ValidationState.warning,\n });\n\n const personaStyles = classNames.subComponentStyles\n ? (classNames.subComponentStyles.persona as IStyleFunctionOrObject<IPersonaStyleProps, IPersonaStyles>)\n : undefined;\n\n const personaCoinStyles = classNames.subComponentStyles\n ? (classNames.subComponentStyles.personaCoin as IStyleFunctionOrObject<IPersonaCoinStyleProps, IPersonaCoinStyles>)\n : undefined;\n\n return (\n <div data-selection-index={index} className={classNames.root} role={'listitem'} key={index} onClick={handleClick}>\n <div className={classNames.itemContent} id={'selectedItemPersona-' + itemId}>\n <Persona size={PersonaSize.size24} styles={personaStyles} coinProps={{ styles: personaCoinStyles }} {...item} />\n </div>\n <IconButton\n componentRef={buttonRef}\n id={itemId}\n onClick={onRemoveItem}\n disabled={disabled}\n iconProps={removeButtonIconProps ?? { iconName: 'Cancel' }}\n styles={{ icon: { fontSize: '12px' } }}\n className={classNames.removeButton}\n ariaLabel={removeButtonAriaLabel}\n aria-labelledby={`${itemId} selectedItemPersona-${itemId}`}\n />\n </div>\n );\n};\n\nexport const PeoplePickerItem = styled<\n IPeoplePickerItemSelectedProps,\n IPeoplePickerItemSelectedStyleProps,\n IPeoplePickerItemSelectedStyles\n>(PeoplePickerItemBase, getStyles, undefined, { scope: 'PeoplePickerItem' });\n"]}
@@ -0,0 +1,2 @@
import type { IPeoplePickerItemSelectedStyleProps, IPeoplePickerItemSelectedStyles } from './PeoplePickerItem.types';
export declare function getStyles(props: IPeoplePickerItemSelectedStyleProps): IPeoplePickerItemSelectedStyles;
@@ -0,0 +1,236 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getStyles = getStyles;
var tslib_1 = require("tslib");
var Styling_1 = require("../../../../Styling");
var BaseButton_classNames_1 = require("../../../Button/BaseButton.classNames");
var GlobalClassNames = {
root: 'ms-PickerPersona-container',
itemContent: 'ms-PickerItem-content',
removeButton: 'ms-PickerItem-removeButton',
isSelected: 'is-selected',
isInvalid: 'is-invalid',
};
var REMOVE_BUTTON_SIZE = 24;
var PICKER_PERSONA_RADIUS = 15;
function getStyles(props) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
var className = props.className, theme = props.theme, selected = props.selected, invalid = props.invalid, disabled = props.disabled;
var palette = theme.palette, semanticColors = theme.semanticColors, fonts = theme.fonts;
var classNames = (0, Styling_1.getGlobalClassNames)(GlobalClassNames, theme);
var personaRootStyles = {
color: 'inherit',
};
// set text color to inherit to allow focus styles to control persona text colors
var personaPrimaryTextStyles = [
selected &&
!invalid &&
!disabled && {
color: 'inherit',
selectors: (_a = {
':hover': {
color: 'inherit',
}
},
_a[Styling_1.HighContrastSelector] = {
color: 'HighlightText',
},
_a),
},
((invalid && !selected) || (invalid && selected && disabled)) && {
color: 'inherit',
borderBottom: "2px dotted currentColor",
selectors: (_b = {},
_b[".".concat(classNames.root, ":hover &")] = {
// override Persona root:hover selector
color: 'inherit',
},
_b),
},
invalid &&
selected &&
!disabled && {
color: 'inherit',
borderBottom: "2px dotted currentColor",
selectors: {
':hover': {
color: 'inherit',
},
},
},
disabled && {
selectors: (_c = {},
_c[Styling_1.HighContrastSelector] = {
color: 'GrayText',
},
_c),
},
];
var personaSecondaryTextStyles = [
selected &&
!invalid &&
!disabled && {
color: 'inherit',
selectors: (_d = {
':hover': {
color: 'inherit',
}
},
_d[Styling_1.HighContrastSelector] = {
color: 'HighlightText',
},
_d),
},
];
var personaCoinInitialsStyles = [
invalid && {
fontSize: fonts.xLarge.fontSize,
},
];
return {
root: [
classNames.root,
(0, Styling_1.getFocusStyle)(theme, { inset: -2 }),
{
borderRadius: PICKER_PERSONA_RADIUS,
display: 'inline-flex',
alignItems: 'center',
background: palette.neutralLighter,
margin: '1px 2px',
cursor: 'default',
userSelect: 'none',
maxWidth: 300,
verticalAlign: 'middle',
minWidth: 0,
selectors: (_e = {
':hover': {
background: !selected && !disabled ? palette.neutralLight : '',
}
},
_e[Styling_1.HighContrastSelector] = [{ border: '1px solid WindowText' }, disabled && { borderColor: 'GrayText' }],
_e),
},
selected &&
!disabled && [
classNames.isSelected,
{
selectors: (_f = {
':focus-within': (_g = {
background: palette.themePrimary,
color: palette.white
},
_g[Styling_1.HighContrastSelector] = {
color: 'HighLightText',
background: 'Highlight',
},
_g)
},
_f[Styling_1.HighContrastSelector] = tslib_1.__assign({ borderColor: 'HighLight', background: 'Highlight' }, (0, Styling_1.getHighContrastNoAdjustStyle)()),
_f),
},
],
invalid && [classNames.isInvalid],
invalid &&
selected &&
!disabled && {
':focus-within': {
background: palette.redDark,
color: palette.white,
},
},
((invalid && !selected) || (invalid && selected && disabled)) && {
color: palette.redDark,
},
className,
],
itemContent: [
classNames.itemContent,
{
flex: '0 1 auto',
minWidth: 0,
// CSS below is needed for IE 11 to properly truncate long persona names in the picker
// and to clip the presence indicator (in all browsers)
maxWidth: '100%',
overflow: 'hidden',
},
],
removeButton: [
classNames.removeButton,
{
borderRadius: PICKER_PERSONA_RADIUS,
color: palette.neutralPrimary,
flex: '0 0 auto',
width: REMOVE_BUTTON_SIZE,
height: REMOVE_BUTTON_SIZE,
selectors: {
':hover': {
background: palette.neutralTertiaryAlt,
color: palette.neutralDark,
},
},
},
selected && [
(0, Styling_1.getFocusStyle)(theme, {
inset: 2,
borderColor: 'transparent',
highContrastStyle: { inset: 2, left: 1, top: 1, bottom: 1, right: 1, outlineColor: 'HighlightText' },
outlineColor: palette.white,
borderRadius: PICKER_PERSONA_RADIUS,
}),
{
selectors: (_h = {
':hover': {
color: palette.white,
background: palette.themeDark,
},
':active': {
color: palette.white,
background: palette.themeDarker,
},
':focus': (_j = {
color: palette.white
},
_j[Styling_1.HighContrastSelector] = {
color: 'HighlightText',
},
_j)
},
_h[Styling_1.HighContrastSelector] = {
color: 'HighlightText',
},
_h),
},
invalid && {
selectors: {
':hover': {
color: palette.white,
background: palette.red,
},
':active': {
color: palette.white,
background: palette.redDark,
},
},
},
],
disabled && {
selectors: (_k = {},
_k[".".concat(BaseButton_classNames_1.ButtonGlobalClassNames.msButtonIcon)] = {
color: semanticColors.buttonText,
},
_k),
},
],
subComponentStyles: {
persona: {
root: personaRootStyles,
primaryText: personaPrimaryTextStyles,
secondaryText: personaSecondaryTextStyles,
},
personaCoin: {
initials: personaCoinInitialsStyles,
},
},
};
}
//# sourceMappingURL=PeoplePickerItem.styles.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,109 @@
import { ValidationState } from '../../BasePicker.types';
import type { IStyle, ITheme } from '../../../../Styling';
import type { IStyleFunctionOrObject } from '../../../../Utilities';
import type { IPersonaProps, IPersonaStyleProps, IPersonaCoinStyleProps } from '../../../../Persona';
import type { IPickerItemProps } from '../../PickerItem.types';
import type { IContextualMenuItem } from '../../../../ContextualMenu';
import type { IBasePickerSuggestionsProps } from '../../BasePicker.types';
/**
* Common props in between IPeoplePickerItemSelectedProps, IPeoplePickerItemWithMenuProps and
* IPeoplePickerItemSuggestionProps.
* {@docCategory PeoplePicker}
*/
export interface IPeoplePickerItemSharedProps {
/** Additional CSS class(es) to apply to the PeoplePickerItem root element. */
className?: string;
/** Theme provided by High-Order Component. */
theme?: ITheme;
}
/**
* PeoplePickerItemSelected props interface. Refers to the PeoplePicker items that have been picked already.
* {@docCategory PeoplePicker}
*/
export interface IPeoplePickerItemSelectedProps extends IPickerItemProps<IPersonaProps & {
ValidationState: ValidationState;
}>, IPeoplePickerItemSharedProps {
/** Call to provide customized styling that will layer on top of the variant rules. */
styles?: IStyleFunctionOrObject<IPeoplePickerItemSelectedStyleProps, IPeoplePickerItemSelectedStyles>;
}
/**
* Props needed to construct PeoplePickerItemSelected styles.
* {@docCategory PeoplePicker}
*/
export type IPeoplePickerItemSelectedStyleProps = Required<Pick<IPeoplePickerItemSelectedProps, 'theme'>> & Pick<IPeoplePickerItemSelectedProps, 'className' | 'selected' | 'disabled'> & {
/** Whether it's invalid. */
invalid?: boolean;
};
/**
* Represents the stylable areas of the PeoplePickerItemSelected.
* {@docCategory PeoplePicker}
*/
export interface IPeoplePickerItemSelectedStyles {
/** Root element of picked PeoplePicker item */
root: IStyle;
/** Refers to the element holding the content (Persona) of the PeoplePicker item already picked. */
itemContent: IStyle;
/** Refers to the remove action button on a picked PeoplePicker item. */
removeButton: IStyle;
/** SubComponent (Persona, PersonaCoin) styles. */
subComponentStyles: IPeoplePickerItemSelectedSubComponentStyles;
}
/**
* Styles interface of the SubComponents rendered within PeoplePickerItemSelected.
* {@docCategory PeoplePicker}
*/
export interface IPeoplePickerItemSelectedSubComponentStyles {
/** Refers to the Persona rendered within the PeoplePickerItemSelected */
persona: IStyleFunctionOrObject<IPersonaStyleProps, any>;
/** Refers to the PersonaCoin in the Persona rendered within the PeoplePickerItemSelected */
personaCoin?: IStyleFunctionOrObject<IPersonaCoinStyleProps, any>;
}
/**
* PeoplePickerItemSuggestion props interface. Refers to the PeoplePicker items that are suggested for picking.
* {@docCategory PeoplePicker}
*/
export interface IPeoplePickerItemSuggestionProps extends IPeoplePickerItemSharedProps {
/** Persona props for each suggested for picking PeoplePicker item. */
personaProps?: IPersonaProps;
/** Call to provide customized styling that will layer on top of the variant rules. */
styles?: IStyleFunctionOrObject<IPeoplePickerItemSuggestionStyleProps, IPeoplePickerItemSuggestionStyles>;
/** General common props for all PeoplePicker items suggestions. */
suggestionsProps?: IBasePickerSuggestionsProps;
/**
* Flag that controls whether each suggested PeoplePicker item (Persona) is rendered with or without secondary text
* for compact look.
* @defaultvalue false
*/
compact?: boolean;
}
/**
* Props needed to construct PeoplePickerItemSuggestion styles.
* {@docCategory PeoplePicker}
*/
export type IPeoplePickerItemSuggestionStyleProps = Required<Pick<IPeoplePickerItemSuggestionProps, 'theme'>> & Pick<IPeoplePickerItemSuggestionProps, 'className'> & {};
/**
* Represents the stylable areas of the PeoplePickerItemSuggestion.
* {@docCategory PeoplePicker}
*/
export interface IPeoplePickerItemSuggestionStyles {
/** Root container element of a suggested PeoplePicker item. */
root: IStyle;
/** Refers to the element wrapping the Persona of the suggested PeoplePicker item. */
personaWrapper: IStyle;
/** SubComponent (Persona, PersonaCoin) styles. */
subComponentStyles: IPeoplePickerItemSelectedSubComponentStyles;
}
/**
* PeoplePickerItemWithMenu props interface.
* @deprecated Do not use. Will be removed in \>= 7.0
*/
export interface IPeoplePickerItemWithMenuProps extends IPickerItemProps<IPersonaWithMenu> {
}
/**
* Extended interface from IPersonaProps to add `menuItems` property PeoplePickerItemWithMenu items.
* @deprecated Do not use. Will be removed in \>= 7.0
*/
export interface IPersonaWithMenu extends IPersonaProps {
/** Additional menuItems to be rendered in a contextualMenu for each Persona. */
menuItems?: IContextualMenuItem[];
}
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=PeoplePickerItem.types.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,5 @@
import * as React from 'react';
import type { IPeoplePickerItemSuggestionProps } from './PeoplePickerItem.types';
import type { JSXElement } from '@fluentui/utilities';
export declare const PeoplePickerItemSuggestionBase: (props: IPeoplePickerItemSuggestionProps) => JSXElement;
export declare const PeoplePickerItemSuggestion: React.FunctionComponent<React.PropsWithChildren<React.PropsWithChildren<IPeoplePickerItemSuggestionProps>>>;
@@ -0,0 +1,24 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PeoplePickerItemSuggestion = exports.PeoplePickerItemSuggestionBase = void 0;
var tslib_1 = require("tslib");
var React = require("react");
var Utilities_1 = require("../../../../Utilities");
var Persona_1 = require("../../../../Persona");
var PeoplePickerItemSuggestion_styles_1 = require("./PeoplePickerItemSuggestion.styles");
var getClassNames = (0, Utilities_1.classNamesFunction)();
var PeoplePickerItemSuggestionBase = function (props) {
var personaProps = props.personaProps, suggestionsProps = props.suggestionsProps, compact = props.compact, styles = props.styles, theme = props.theme, className = props.className;
var classNames = getClassNames(styles, {
theme: theme,
className: (suggestionsProps && suggestionsProps.suggestionsItemClassName) || className,
});
var personaStyles = classNames.subComponentStyles && classNames.subComponentStyles.persona
? classNames.subComponentStyles.persona
: undefined;
return (React.createElement("div", { className: classNames.root },
React.createElement(Persona_1.Persona, tslib_1.__assign({ size: Persona_1.PersonaSize.size24, styles: personaStyles, className: classNames.personaWrapper, showSecondaryText: !compact, showOverflowTooltip: false }, personaProps))));
};
exports.PeoplePickerItemSuggestionBase = PeoplePickerItemSuggestionBase;
exports.PeoplePickerItemSuggestion = (0, Utilities_1.styled)(exports.PeoplePickerItemSuggestionBase, PeoplePickerItemSuggestion_styles_1.getStyles, undefined, { scope: 'PeoplePickerItemSuggestion' });
//# sourceMappingURL=PeoplePickerItemSuggestion.js.map
@@ -0,0 +1 @@
{"version":3,"file":"PeoplePickerItemSuggestion.js","sourceRoot":"../src/","sources":["components/pickers/PeoplePicker/PeoplePickerItems/PeoplePickerItemSuggestion.tsx"],"names":[],"mappings":";;;;AAAA,6BAA+B;AAE/B,mDAAmE;AACnE,+CAA2D;AAC3D,yFAAgE;AAWhE,IAAM,aAAa,GAAG,IAAA,8BAAkB,GAA4E,CAAC;AAE9G,IAAM,8BAA8B,GAAG,UAAC,KAAuC;IAC5E,IAAA,YAAY,GAA0D,KAAK,aAA/D,EAAE,gBAAgB,GAAwC,KAAK,iBAA7C,EAAE,OAAO,GAA+B,KAAK,QAApC,EAAE,MAAM,GAAuB,KAAK,OAA5B,EAAE,KAAK,GAAgB,KAAK,MAArB,EAAE,SAAS,GAAK,KAAK,UAAV,CAAW;IAEpF,IAAM,UAAU,GAAG,aAAa,CAAC,MAAM,EAAE;QACvC,KAAK,EAAE,KAAM;QACb,SAAS,EAAE,CAAC,gBAAgB,IAAI,gBAAgB,CAAC,wBAAwB,CAAC,IAAI,SAAS;KACxF,CAAC,CAAC;IAEH,IAAM,aAAa,GACjB,UAAU,CAAC,kBAAkB,IAAI,UAAU,CAAC,kBAAkB,CAAC,OAAO;QACpE,CAAC,CAAE,UAAU,CAAC,kBAAkB,CAAC,OAAsE;QACvG,CAAC,CAAC,SAAS,CAAC;IAEhB,OAAO,CACL,6BAAK,SAAS,EAAE,UAAU,CAAC,IAAI;QAC7B,oBAAC,iBAAO,qBACN,IAAI,EAAE,qBAAW,CAAC,MAAM,EACxB,MAAM,EAAE,aAAa,EACrB,SAAS,EAAE,UAAU,CAAC,cAAc,EACpC,iBAAiB,EAAE,CAAC,OAAO,EAC3B,mBAAmB,EAAE,KAAK,IACtB,YAAY,EAChB,CACE,CACP,CAAC;AACJ,CAAC,CAAC;AAzBW,QAAA,8BAA8B,kCAyBzC;AAEW,QAAA,0BAA0B,GAAG,IAAA,kBAAM,EAI9C,sCAA8B,EAAE,6CAAS,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,4BAA4B,EAAE,CAAC,CAAC","sourcesContent":["import * as React from 'react';\n\nimport { classNamesFunction, styled } from '../../../../Utilities';\nimport { Persona, PersonaSize } from '../../../../Persona';\nimport { getStyles } from './PeoplePickerItemSuggestion.styles';\nimport type { IStyleFunctionOrObject } from '../../../../Utilities';\nimport type { IPersonaStyleProps, IPersonaStyles } from '../../../../Persona';\nimport type {\n IPeoplePickerItemSuggestionProps,\n IPeoplePickerItemSuggestionStyleProps,\n IPeoplePickerItemSuggestionStyles,\n} from './PeoplePickerItem.types';\n\nimport type { JSXElement } from '@fluentui/utilities';\n\nconst getClassNames = classNamesFunction<IPeoplePickerItemSuggestionStyleProps, IPeoplePickerItemSuggestionStyles>();\n\nexport const PeoplePickerItemSuggestionBase = (props: IPeoplePickerItemSuggestionProps): JSXElement => {\n const { personaProps, suggestionsProps, compact, styles, theme, className } = props;\n\n const classNames = getClassNames(styles, {\n theme: theme!,\n className: (suggestionsProps && suggestionsProps.suggestionsItemClassName) || className,\n });\n\n const personaStyles =\n classNames.subComponentStyles && classNames.subComponentStyles.persona\n ? (classNames.subComponentStyles.persona as IStyleFunctionOrObject<IPersonaStyleProps, IPersonaStyles>)\n : undefined;\n\n return (\n <div className={classNames.root}>\n <Persona\n size={PersonaSize.size24}\n styles={personaStyles}\n className={classNames.personaWrapper}\n showSecondaryText={!compact}\n showOverflowTooltip={false}\n {...personaProps}\n />\n </div>\n );\n};\n\nexport const PeoplePickerItemSuggestion = styled<\n IPeoplePickerItemSuggestionProps,\n IPeoplePickerItemSuggestionStyleProps,\n IPeoplePickerItemSuggestionStyles\n>(PeoplePickerItemSuggestionBase, getStyles, undefined, { scope: 'PeoplePickerItemSuggestion' });\n"]}
@@ -0,0 +1,2 @@
import type { IPeoplePickerItemSuggestionStyles, IPeoplePickerItemSuggestionStyleProps } from './PeoplePickerItem.types';
export declare function getStyles(props: IPeoplePickerItemSuggestionStyleProps): IPeoplePickerItemSuggestionStyles;
@@ -0,0 +1,55 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getStyles = getStyles;
var Styling_1 = require("../../../../Styling");
var SuggestionsItem_styles_1 = require("../../Suggestions/SuggestionsItem.styles");
var GlobalClassNames = {
root: 'ms-PeoplePicker-personaContent',
personaWrapper: 'ms-PeoplePicker-Persona',
};
function getStyles(props) {
var _a, _b, _c;
var className = props.className, theme = props.theme;
var classNames = (0, Styling_1.getGlobalClassNames)(GlobalClassNames, theme);
var textSelectorsStyles = {
selectors: (_a = {},
_a[".".concat(SuggestionsItem_styles_1.SuggestionsItemGlobalClassNames.isSuggested, " &")] = {
selectors: (_b = {},
_b[Styling_1.HighContrastSelector] = {
color: 'HighlightText',
},
_b),
},
_a[".".concat(classNames.root, ":hover &")] = {
selectors: (_c = {},
_c[Styling_1.HighContrastSelector] = {
color: 'HighlightText',
},
_c),
},
_a),
};
return {
root: [
classNames.root,
{
width: '100%',
padding: '4px 12px',
},
className,
],
personaWrapper: [
classNames.personaWrapper,
{
width: 180,
},
],
subComponentStyles: {
persona: {
primaryText: textSelectorsStyles,
secondaryText: textSelectorsStyles,
},
},
};
}
//# sourceMappingURL=PeoplePickerItemSuggestion.styles.js.map
@@ -0,0 +1 @@
{"version":3,"file":"PeoplePickerItemSuggestion.styles.js","sourceRoot":"../src/","sources":["components/pickers/PeoplePicker/PeoplePickerItems/PeoplePickerItemSuggestion.styles.ts"],"names":[],"mappings":";;AAaA,8BA6CC;AA1DD,+CAAgF;AAChF,mFAAwG;AAOxG,IAAM,gBAAgB,GAAG;IACvB,IAAI,EAAE,gCAAgC;IACtC,cAAc,EAAE,yBAAyB;CAC1C,CAAC;AAEF,SAAgB,SAAS,CAAC,KAA4C;;IAC5D,IAAA,SAAS,GAAY,KAAK,UAAjB,EAAE,KAAK,GAAK,KAAK,MAAV,CAAW;IACnC,IAAM,UAAU,GAAG,IAAA,6BAAmB,EAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;IAEhE,IAAM,mBAAmB,GAAW;QAClC,SAAS;YACP,GAAC,WAAI,wDAAS,CAAC,WAAW,OAAI,IAAG;gBAC/B,SAAS;oBACP,GAAC,8BAAoB,IAAG;wBACtB,KAAK,EAAE,eAAe;qBACvB;uBACF;aACF;YACD,GAAC,WAAI,UAAU,CAAC,IAAI,aAAU,IAAG;gBAC/B,SAAS;oBACP,GAAC,8BAAoB,IAAG;wBACtB,KAAK,EAAE,eAAe;qBACvB;uBACF;aACF;eACF;KACF,CAAC;IAEF,OAAO;QACL,IAAI,EAAE;YACJ,UAAU,CAAC,IAAI;YACf;gBACE,KAAK,EAAE,MAAM;gBACb,OAAO,EAAE,UAAU;aACpB;YACD,SAAS;SACV;QACD,cAAc,EAAE;YACd,UAAU,CAAC,cAAc;YACzB;gBACE,KAAK,EAAE,GAAG;aACX;SACF;QACD,kBAAkB,EAAE;YAClB,OAAO,EAAE;gBACP,WAAW,EAAE,mBAAmB;gBAChC,aAAa,EAAE,mBAAmB;aACnC;SACF;KACF,CAAC;AACJ,CAAC","sourcesContent":["import { getGlobalClassNames, HighContrastSelector } from '../../../../Styling';\nimport { SuggestionsItemGlobalClassNames as suggested } from '../../Suggestions/SuggestionsItem.styles';\nimport type { IStyle } from '../../../../Styling';\nimport type {\n IPeoplePickerItemSuggestionStyles,\n IPeoplePickerItemSuggestionStyleProps,\n} from './PeoplePickerItem.types';\n\nconst GlobalClassNames = {\n root: 'ms-PeoplePicker-personaContent',\n personaWrapper: 'ms-PeoplePicker-Persona',\n};\n\nexport function getStyles(props: IPeoplePickerItemSuggestionStyleProps): IPeoplePickerItemSuggestionStyles {\n const { className, theme } = props;\n const classNames = getGlobalClassNames(GlobalClassNames, theme);\n\n const textSelectorsStyles: IStyle = {\n selectors: {\n [`.${suggested.isSuggested} &`]: {\n selectors: {\n [HighContrastSelector]: {\n color: 'HighlightText',\n },\n },\n },\n [`.${classNames.root}:hover &`]: {\n selectors: {\n [HighContrastSelector]: {\n color: 'HighlightText',\n },\n },\n },\n },\n };\n\n return {\n root: [\n classNames.root,\n {\n width: '100%',\n padding: '4px 12px',\n },\n className,\n ],\n personaWrapper: [\n classNames.personaWrapper,\n {\n width: 180,\n },\n ],\n subComponentStyles: {\n persona: {\n primaryText: textSelectorsStyles,\n secondaryText: textSelectorsStyles,\n },\n },\n };\n}\n"]}
@@ -0,0 +1,7 @@
export declare const personaContainer = "personaContainer_a108c744";
export declare const removeButton = "removeButton_a108c744";
export declare const personaContainerIsSelected = "personaContainerIsSelected_a108c744";
export declare const validationError = "validationError_a108c744";
export declare const itemContent = "itemContent_a108c744";
export declare const personaDetails = "personaDetails_a108c744";
export declare const itemContainer = "itemContainer_a108c744";
@@ -0,0 +1,14 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.itemContainer = exports.personaDetails = exports.itemContent = exports.validationError = exports.personaContainerIsSelected = exports.removeButton = exports.personaContainer = void 0;
/* eslint-disable */
var load_themed_styles_1 = require("@microsoft/load-themed-styles");
(0, load_themed_styles_1.loadStyles)([{ "rawString": ".personaContainer_a108c744{border-radius:15px;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;background:" }, { "theme": "neutralLighter", "defaultValue": "#f3f2f1" }, { "rawString": ";margin:1px 2px;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;max-width:300px;vertical-align:middle}.personaContainer_a108c744::-moz-focus-inner{border:0}.personaContainer_a108c744{outline:transparent}.personaContainer_a108c744{position:relative}.ms-Fabric--isFocusVisible .personaContainer_a108c744:focus:after{-webkit-box-sizing:border-box;box-sizing:border-box;content:\"\";position:absolute;top:-2px;right:-2px;bottom:-2px;left:-2px;pointer-events:none;border:1px solid " }, { "theme": "focusBorder", "defaultValue": "#605e5c" }, { "rawString": ";border-radius:0}.personaContainer_a108c744:hover{background:" }, { "theme": "neutralLight", "defaultValue": "#edebe9" }, { "rawString": "}.personaContainer_a108c744:hover .removeButton_a108c744{color:" }, { "theme": "neutralPrimary", "defaultValue": "#323130" }, { "rawString": "}.personaContainer_a108c744.personaContainerIsSelected_a108c744{background:" }, { "theme": "blue", "defaultValue": "#0078d4" }, { "rawString": "}.personaContainer_a108c744.personaContainerIsSelected_a108c744 .ms-Persona-primaryText{color:" }, { "theme": "white", "defaultValue": "#ffffff" }, { "rawString": "}@media screen and (-ms-high-contrast:active),screen and (forced-colors:active){.personaContainer_a108c744.personaContainerIsSelected_a108c744 .ms-Persona-primaryText{color:HighlightText}}.personaContainer_a108c744.personaContainerIsSelected_a108c744 .removeButton_a108c744 .ms-Button-icon{color:" }, { "theme": "white", "defaultValue": "#ffffff" }, { "rawString": "}@media screen and (-ms-high-contrast:active),screen and (forced-colors:active){.personaContainer_a108c744.personaContainerIsSelected_a108c744 .removeButton_a108c744 .ms-Button-icon{color:HighlightText}}.personaContainer_a108c744.personaContainerIsSelected_a108c744 .removeButton_a108c744:hover{color:" }, { "theme": "white", "defaultValue": "#ffffff" }, { "rawString": ";background:" }, { "theme": "themeDark", "defaultValue": "#005a9e" }, { "rawString": "}@media screen and (-ms-high-contrast:active),screen and (forced-colors:active){.personaContainer_a108c744.personaContainerIsSelected_a108c744{border-color:Highlight;background:Highlight;-ms-high-contrast-adjust:none}}.personaContainer_a108c744.validationError_a108c744 .ms-Persona-primaryText{color:" }, { "theme": "redDark", "defaultValue": "#a4262c" }, { "rawString": ";border-bottom:2px dotted " }, { "theme": "redDark", "defaultValue": "#a4262c" }, { "rawString": "}.personaContainer_a108c744.validationError_a108c744 .ms-Persona-initials{font-size:20px}.personaContainer_a108c744.validationError_a108c744.personaContainerIsSelected_a108c744{background:" }, { "theme": "redDark", "defaultValue": "#a4262c" }, { "rawString": "}.personaContainer_a108c744.validationError_a108c744.personaContainerIsSelected_a108c744 .ms-Persona-primaryText{color:" }, { "theme": "white", "defaultValue": "#ffffff" }, { "rawString": ";border-bottom:2px dotted " }, { "theme": "white", "defaultValue": "#ffffff" }, { "rawString": "}.personaContainer_a108c744.validationError_a108c744.personaContainerIsSelected_a108c744 .removeButton_a108c744:hover{background:" }, { "theme": "red", "defaultValue": "#e81123" }, { "rawString": "}@media screen and (-ms-high-contrast:active),screen and (forced-colors:active){.personaContainer_a108c744{border:1px solid WindowText}}.personaContainer_a108c744 .itemContent_a108c744{-webkit-box-flex:0;-ms-flex:0 1 auto;flex:0 1 auto;min-width:0;max-width:100%;overflow:hidden}.personaContainer_a108c744 .removeButton_a108c744{border-radius:15px;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;width:28px;height:28px;-ms-flex-preferred-size:28px;flex-basis:28px}.personaContainer_a108c744 .removeButton_a108c744:hover{background:" }, { "theme": "neutralTertiaryAlt", "defaultValue": "#c8c6c4" }, { "rawString": ";color:" }, { "theme": "neutralDark", "defaultValue": "#201f1e" }, { "rawString": "}.personaContainer_a108c744 .personaDetails_a108c744{-webkit-box-flex:0;-ms-flex:0 1 auto;flex:0 1 auto}.itemContainer_a108c744{display:inline-block;vertical-align:top}" }]);
exports.personaContainer = "personaContainer_a108c744";
exports.removeButton = "removeButton_a108c744";
exports.personaContainerIsSelected = "personaContainerIsSelected_a108c744";
exports.validationError = "validationError_a108c744";
exports.itemContent = "itemContent_a108c744";
exports.personaDetails = "personaDetails_a108c744";
exports.itemContainer = "itemContainer_a108c744";
//# sourceMappingURL=PickerItemsDefault.scss.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,6 @@
import type { IPeoplePickerItemSelectedProps } from './PeoplePickerItem.types';
import type { JSXElement } from '@fluentui/utilities';
/**
* @deprecated Use `PeoplePickerItem` instead. Will be removed in \>= 7.0.
*/
export declare const SelectedItemDefault: (props: IPeoplePickerItemSelectedProps) => JSXElement;
@@ -0,0 +1,32 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SelectedItemDefault = void 0;
var tslib_1 = require("tslib");
var React = require("react");
var Utilities_1 = require("../../../../Utilities");
var Persona_1 = require("../../../../Persona");
var BasePicker_types_1 = require("../../BasePicker.types");
var Button_1 = require("../../../../Button");
var stylesImport = require("./PickerItemsDefault.scss");
var styles = stylesImport;
/**
* @deprecated Use `PeoplePickerItem` instead. Will be removed in \>= 7.0.
*/
var SelectedItemDefault = function (peoplePickerItemProps) {
var _a, _b;
var item = peoplePickerItemProps.item, onRemoveItem = peoplePickerItemProps.onRemoveItem, index = peoplePickerItemProps.index, selected = peoplePickerItemProps.selected, removeButtonAriaLabel = peoplePickerItemProps.removeButtonAriaLabel;
var itemId = (0, Utilities_1.getId)();
var onClickIconButton = function (removeItem) {
return function () {
if (removeItem) {
removeItem();
}
};
};
return (React.createElement("div", { className: (0, Utilities_1.css)('ms-PickerPersona-container', styles.personaContainer, (_a = {}, _a['is-selected ' + styles.personaContainerIsSelected] = selected, _a), (_b = {}, _b['is-invalid ' + styles.validationError] = item.ValidationState === BasePicker_types_1.ValidationState.warning, _b)), "data-is-focusable": true, "data-is-sub-focuszone": true, "data-selection-index": index, role: 'listitem', "aria-labelledby": 'selectedItemPersona-' + itemId },
React.createElement("div", { className: (0, Utilities_1.css)('ms-PickerItem-content', styles.itemContent), id: 'selectedItemPersona-' + itemId },
React.createElement(Persona_1.Persona, tslib_1.__assign({}, item, { presence: item.presence !== undefined ? item.presence : Persona_1.PersonaPresence.none, size: Persona_1.PersonaSize.size28 }))),
React.createElement(Button_1.IconButton, { onClick: onClickIconButton(onRemoveItem), iconProps: { iconName: 'Cancel', style: { fontSize: '12px' } }, className: (0, Utilities_1.css)('ms-PickerItem-removeButton', styles.removeButton), ariaLabel: removeButtonAriaLabel })));
};
exports.SelectedItemDefault = SelectedItemDefault;
//# sourceMappingURL=SelectedItemDefault.js.map
@@ -0,0 +1 @@
{"version":3,"file":"SelectedItemDefault.js","sourceRoot":"../src/","sources":["components/pickers/PeoplePicker/PeoplePickerItems/SelectedItemDefault.tsx"],"names":[],"mappings":";;;;AAAA,6BAA+B;AAE/B,mDAAmD;AACnD,+CAA4E;AAC5E,2DAAyD;AACzD,6CAAgD;AAEhD,wDAA0D;AAK1D,IAAM,MAAM,GAAQ,YAAY,CAAC;AAEjC;;GAEG;AAEI,IAAM,mBAAmB,GAA0D,UACxF,qBAAqD;;IAE7C,IAAA,IAAI,GAA2D,qBAAqB,KAAhF,EAAE,YAAY,GAA6C,qBAAqB,aAAlE,EAAE,KAAK,GAAsC,qBAAqB,MAA3D,EAAE,QAAQ,GAA4B,qBAAqB,SAAjD,EAAE,qBAAqB,GAAK,qBAAqB,sBAA1B,CAA2B;IAE7F,IAAM,MAAM,GAAG,IAAA,iBAAK,GAAE,CAAC;IACvB,IAAM,iBAAiB,GAAG,UAAC,UAAoC;QAC7D,OAAO;YACL,IAAI,UAAU,EAAE,CAAC;gBACf,UAAU,EAAE,CAAC;YACf,CAAC;QACH,CAAC,CAAC;IACJ,CAAC,CAAC;IAEF,OAAO,CACL,6BACE,SAAS,EAAE,IAAA,eAAG,EACZ,4BAA4B,EAC5B,MAAM,CAAC,gBAAgB,YACrB,GAAC,cAAc,GAAG,MAAM,CAAC,0BAA0B,IAAG,QAAQ,iBAC9D,GAAC,aAAa,GAAG,MAAM,CAAC,eAAe,IAAG,IAAI,CAAC,eAAe,KAAK,kCAAe,CAAC,OAAO,MAC7F,uBACkB,IAAI,2BACA,IAAI,0BACL,KAAK,EAC3B,IAAI,EAAE,UAAU,qBACC,sBAAsB,GAAG,MAAM;QAEhD,6BAAK,SAAS,EAAE,IAAA,eAAG,EAAC,uBAAuB,EAAE,MAAM,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,sBAAsB,GAAG,MAAM;YACnG,oBAAC,iBAAO,uBACF,IAAI,IACR,QAAQ,EAAE,IAAI,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,yBAAe,CAAC,IAAI,EAC5E,IAAI,EAAE,qBAAW,CAAC,MAAM,IACxB,CACE;QACN,oBAAC,mBAAU,IACT,OAAO,EAAE,iBAAiB,CAAC,YAAY,CAAC,EACxC,SAAS,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAC9D,SAAS,EAAE,IAAA,eAAG,EAAC,4BAA4B,EAAE,MAAM,CAAC,YAAY,CAAC,EACjE,SAAS,EAAE,qBAAqB,GAChC,CACE,CACP,CAAC;AACJ,CAAC,CAAC;AA3CW,QAAA,mBAAmB,uBA2C9B","sourcesContent":["import * as React from 'react';\n\nimport { css, getId } from '../../../../Utilities';\nimport { Persona, PersonaSize, PersonaPresence } from '../../../../Persona';\nimport { ValidationState } from '../../BasePicker.types';\nimport { IconButton } from '../../../../Button';\n\nimport * as stylesImport from './PickerItemsDefault.scss';\nimport type { IPeoplePickerItemSelectedProps } from './PeoplePickerItem.types';\n\nimport type { JSXElement } from '@fluentui/utilities';\n\nconst styles: any = stylesImport;\n\n/**\n * @deprecated Use `PeoplePickerItem` instead. Will be removed in \\>= 7.0.\n */\n\nexport const SelectedItemDefault: (props: IPeoplePickerItemSelectedProps) => JSXElement = (\n peoplePickerItemProps: IPeoplePickerItemSelectedProps,\n) => {\n const { item, onRemoveItem, index, selected, removeButtonAriaLabel } = peoplePickerItemProps;\n\n const itemId = getId();\n const onClickIconButton = (removeItem: (() => void) | undefined): (() => void) => {\n return (): void => {\n if (removeItem) {\n removeItem();\n }\n };\n };\n\n return (\n <div\n className={css(\n 'ms-PickerPersona-container',\n styles.personaContainer,\n { ['is-selected ' + styles.personaContainerIsSelected]: selected },\n { ['is-invalid ' + styles.validationError]: item.ValidationState === ValidationState.warning },\n )}\n data-is-focusable={true}\n data-is-sub-focuszone={true}\n data-selection-index={index}\n role={'listitem'}\n aria-labelledby={'selectedItemPersona-' + itemId}\n >\n <div className={css('ms-PickerItem-content', styles.itemContent)} id={'selectedItemPersona-' + itemId}>\n <Persona\n {...item}\n presence={item.presence !== undefined ? item.presence : PersonaPresence.none}\n size={PersonaSize.size28} // eslint-disable-line @typescript-eslint/no-deprecated\n />\n </div>\n <IconButton\n onClick={onClickIconButton(onRemoveItem)}\n iconProps={{ iconName: 'Cancel', style: { fontSize: '12px' } }}\n className={css('ms-PickerItem-removeButton', styles.removeButton)}\n ariaLabel={removeButtonAriaLabel}\n />\n </div>\n );\n};\n"]}
@@ -0,0 +1,11 @@
import type { IPersonaProps } from '../../../../Persona';
import type { IBasePickerSuggestionsProps } from '../../../../Pickers';
import type { JSXElement } from '@fluentui/utilities';
/**
* @deprecated Use `PeoplePickerItemSuggestion` instead. Will be removed in \>= 7.0.
*/
export declare const SuggestionItemNormal: (persona: IPersonaProps, suggestionProps?: IBasePickerSuggestionsProps) => JSXElement;
/**
* @deprecated Use `PeoplePickerItemSuggestion` with `compact` prop set to `true`. Will be removed in \>= 7.0.
*/
export declare const SuggestionItemSmall: (persona: IPersonaProps, suggestionProps?: IBasePickerSuggestionsProps) => JSXElement;
@@ -0,0 +1,26 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SuggestionItemSmall = exports.SuggestionItemNormal = void 0;
var tslib_1 = require("tslib");
var React = require("react");
var Utilities_1 = require("../../../../Utilities");
var Persona_1 = require("../../../../Persona");
var stylesImport = require("./SuggestionItemDefault.scss");
var styles = stylesImport;
/**
* @deprecated Use `PeoplePickerItemSuggestion` instead. Will be removed in \>= 7.0.
*/
var SuggestionItemNormal = function (personaProps, suggestionItemProps) {
return (React.createElement("div", { className: (0, Utilities_1.css)('ms-PeoplePicker-personaContent', styles.peoplePickerPersonaContent) },
React.createElement(Persona_1.Persona, tslib_1.__assign({ presence: personaProps.presence !== undefined ? personaProps.presence : Persona_1.PersonaPresence.none, size: Persona_1.PersonaSize.size24, className: (0, Utilities_1.css)('ms-PeoplePicker-Persona', styles.peoplePickerPersona), showSecondaryText: true }, personaProps))));
};
exports.SuggestionItemNormal = SuggestionItemNormal;
/**
* @deprecated Use `PeoplePickerItemSuggestion` with `compact` prop set to `true`. Will be removed in \>= 7.0.
*/
var SuggestionItemSmall = function (personaProps, suggestionItemProps) {
return (React.createElement("div", { className: (0, Utilities_1.css)('ms-PeoplePicker-personaContent', styles.peoplePickerPersonaContent) },
React.createElement(Persona_1.Persona, tslib_1.__assign({ presence: personaProps.presence !== undefined ? personaProps.presence : Persona_1.PersonaPresence.none, size: Persona_1.PersonaSize.size24, className: (0, Utilities_1.css)('ms-PeoplePicker-Persona', styles.peoplePickerPersona) }, personaProps))));
};
exports.SuggestionItemSmall = SuggestionItemSmall;
//# sourceMappingURL=SuggestionItemDefault.js.map
@@ -0,0 +1 @@
{"version":3,"file":"SuggestionItemDefault.js","sourceRoot":"../src/","sources":["components/pickers/PeoplePicker/PeoplePickerItems/SuggestionItemDefault.tsx"],"names":[],"mappings":";;;;AAAA,6BAA+B;AAE/B,mDAA4C;AAC5C,+CAA4E;AAC5E,2DAA6D;AAM7D,IAAM,MAAM,GAAQ,YAAY,CAAC;AAEjC;;GAEG;AACI,IAAM,oBAAoB,GAGf,UAAC,YAA2B,EAAE,mBAA+C;IAC7F,OAAO,CACL,6BAAK,SAAS,EAAE,IAAA,eAAG,EAAC,gCAAgC,EAAE,MAAM,CAAC,0BAA0B,CAAC;QACtF,oBAAC,iBAAO,qBACN,QAAQ,EAAE,YAAY,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,yBAAe,CAAC,IAAI,EAC5F,IAAI,EAAE,qBAAW,CAAC,MAAM,EACxB,SAAS,EAAE,IAAA,eAAG,EAAC,yBAAyB,EAAE,MAAM,CAAC,mBAAmB,CAAC,EACrE,iBAAiB,EAAE,IAAI,IACnB,YAAY,EAChB,CACE,CACP,CAAC;AACJ,CAAC,CAAC;AAfW,QAAA,oBAAoB,wBAe/B;AAEF;;GAEG;AACI,IAAM,mBAAmB,GAGd,UAAC,YAA2B,EAAE,mBAA+C;IAC7F,OAAO,CACL,6BAAK,SAAS,EAAE,IAAA,eAAG,EAAC,gCAAgC,EAAE,MAAM,CAAC,0BAA0B,CAAC;QACtF,oBAAC,iBAAO,qBACN,QAAQ,EAAE,YAAY,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,yBAAe,CAAC,IAAI,EAC5F,IAAI,EAAE,qBAAW,CAAC,MAAM,EACxB,SAAS,EAAE,IAAA,eAAG,EAAC,yBAAyB,EAAE,MAAM,CAAC,mBAAmB,CAAC,IACjE,YAAY,EAChB,CACE,CACP,CAAC;AACJ,CAAC,CAAC;AAdW,QAAA,mBAAmB,uBAc9B","sourcesContent":["import * as React from 'react';\n\nimport { css } from '../../../../Utilities';\nimport { Persona, PersonaSize, PersonaPresence } from '../../../../Persona';\nimport * as stylesImport from './SuggestionItemDefault.scss';\nimport type { IPersonaProps } from '../../../../Persona';\nimport type { IBasePickerSuggestionsProps, ISuggestionItemProps } from '../../../../Pickers';\n\nimport type { JSXElement } from '@fluentui/utilities';\n\nconst styles: any = stylesImport;\n\n/**\n * @deprecated Use `PeoplePickerItemSuggestion` instead. Will be removed in \\>= 7.0.\n */\nexport const SuggestionItemNormal: (\n persona: IPersonaProps,\n suggestionProps?: IBasePickerSuggestionsProps,\n) => JSXElement = (personaProps: IPersonaProps, suggestionItemProps?: ISuggestionItemProps<any>) => {\n return (\n <div className={css('ms-PeoplePicker-personaContent', styles.peoplePickerPersonaContent)}>\n <Persona\n presence={personaProps.presence !== undefined ? personaProps.presence : PersonaPresence.none}\n size={PersonaSize.size24}\n className={css('ms-PeoplePicker-Persona', styles.peoplePickerPersona)}\n showSecondaryText={true}\n {...personaProps}\n />\n </div>\n );\n};\n\n/**\n * @deprecated Use `PeoplePickerItemSuggestion` with `compact` prop set to `true`. Will be removed in \\>= 7.0.\n */\nexport const SuggestionItemSmall: (\n persona: IPersonaProps,\n suggestionProps?: IBasePickerSuggestionsProps,\n) => JSXElement = (personaProps: IPersonaProps, suggestionItemProps?: ISuggestionItemProps<any>) => {\n return (\n <div className={css('ms-PeoplePicker-personaContent', styles.peoplePickerPersonaContent)}>\n <Persona\n presence={personaProps.presence !== undefined ? personaProps.presence : PersonaPresence.none}\n size={PersonaSize.size24}\n className={css('ms-PeoplePicker-Persona', styles.peoplePickerPersona)}\n {...personaProps}\n />\n </div>\n );\n};\n"]}
@@ -0,0 +1,2 @@
export declare const peoplePickerPersona = "peoplePickerPersona_37959c1f";
export declare const peoplePickerPersonaContent = "peoplePickerPersonaContent_37959c1f";
@@ -0,0 +1,9 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.peoplePickerPersonaContent = exports.peoplePickerPersona = void 0;
/* eslint-disable */
var load_themed_styles_1 = require("@microsoft/load-themed-styles");
(0, load_themed_styles_1.loadStyles)([{ "rawString": ".peoplePickerPersona_37959c1f{width:180px}.peoplePickerPersonaContent_37959c1f{display:-webkit-box;display:-ms-flexbox;display:flex;width:100%;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:7px 12px}" }]);
exports.peoplePickerPersona = "peoplePickerPersona_37959c1f";
exports.peoplePickerPersonaContent = "peoplePickerPersonaContent_37959c1f";
//# sourceMappingURL=SuggestionItemDefault.scss.js.map
@@ -0,0 +1 @@
{"version":3,"file":"SuggestionItemDefault.scss.js","sourceRoot":"../src/","sources":["components/pickers/PeoplePicker/PeoplePickerItems/SuggestionItemDefault.scss.ts"],"names":[],"mappings":";;;AAAA,oBAAoB;AACpB,oEAA2D;AAC3D,IAAA,+BAAU,EAAC,CAAC,EAAC,WAAW,EAAC,iTAAiT,EAAC,CAAC,CAAC,CAAC;AACjU,QAAA,mBAAmB,GAAG,8BAA8B,CAAC;AACrD,QAAA,0BAA0B,GAAG,qCAAqC,CAAC","sourcesContent":["/* eslint-disable */\nimport { loadStyles } from '@microsoft/load-themed-styles';\nloadStyles([{\"rawString\":\".peoplePickerPersona_37959c1f{width:180px}.peoplePickerPersonaContent_37959c1f{display:-webkit-box;display:-ms-flexbox;display:flex;width:100%;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:7px 12px}\"}]);\nexport const peoplePickerPersona = \"peoplePickerPersona_37959c1f\";\nexport const peoplePickerPersonaContent = \"peoplePickerPersonaContent_37959c1f\";"]}
@@ -0,0 +1,42 @@
import * as React from 'react';
import type { IRefObject } from '../../Utilities';
import { IIconProps } from '../Icon/Icon.types';
/**
* PickerItem component.
* {@docCategory Pickers}
*/
export interface IPickerItem {
}
/**
* PickerItem props common for any type of items.
* {@docCategory Pickers}
*/
export interface IPickerItemProps<T> extends React.AllHTMLAttributes<HTMLElement> {
/**
* Optional callback to access the IPickerItem interface. Use this instead of ref for accessing
* the public methods and properties of the component.
*/
componentRef?: IRefObject<IPickerItem>;
/** The item of Type T (Persona, Tag, or any other custom item provided). */
item: T;
/** Index number of the item in the array of picked items. */
index: number;
/** Whether the picked item is selected or not. */
selected?: boolean;
/** Callback issued when the item is removed from the array of picked items. */
onRemoveItem?: () => void;
/**
* Internal Use only, gives a callback to the renderer to call when an item has changed.
* This allows the base picker to keep track of changes in the items.
*/
onItemChange?: (item: T, index: number) => void;
/** Unique key for each picked item. */
key?: string | number;
/** Aria-label for the picked item remove button. */
removeButtonAriaLabel?: string;
/**
* Props for the icon used in the remove button.
* @defaultvalue `{ iconName:'Cancel' }`
*/
removeButtonIconProps?: IIconProps;
}
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=PickerItem.types.js.map
@@ -0,0 +1 @@
{"version":3,"file":"PickerItem.types.js","sourceRoot":"../src/","sources":["components/pickers/PickerItem.types.ts"],"names":[],"mappings":"","sourcesContent":["import * as React from 'react';\nimport type { IRefObject } from '../../Utilities';\nimport { IIconProps } from '../Icon/Icon.types';\n/**\n * PickerItem component.\n * {@docCategory Pickers}\n */\nexport interface IPickerItem {}\n\n/**\n * PickerItem props common for any type of items.\n * {@docCategory Pickers}\n */\nexport interface IPickerItemProps<T> extends React.AllHTMLAttributes<HTMLElement> {\n /**\n * Optional callback to access the IPickerItem interface. Use this instead of ref for accessing\n * the public methods and properties of the component.\n */\n componentRef?: IRefObject<IPickerItem>;\n\n /** The item of Type T (Persona, Tag, or any other custom item provided). */\n item: T;\n\n /** Index number of the item in the array of picked items. */\n index: number;\n\n /** Whether the picked item is selected or not. */\n selected?: boolean;\n\n /** Callback issued when the item is removed from the array of picked items. */\n onRemoveItem?: () => void;\n\n /**\n * Internal Use only, gives a callback to the renderer to call when an item has changed.\n * This allows the base picker to keep track of changes in the items.\n */\n onItemChange?: (item: T, index: number) => void;\n\n /** Unique key for each picked item. */\n key?: string | number;\n\n /** Aria-label for the picked item remove button. */\n removeButtonAriaLabel?: string;\n\n /**\n * Props for the icon used in the remove button.\n * @defaultvalue `{ iconName:'Cancel' }`\n */\n removeButtonIconProps?: IIconProps;\n}\n"]}
@@ -0,0 +1,42 @@
import * as React from 'react';
import { SuggestionActionType } from './Suggestions.types';
import type { IButton } from '../../../Button';
import type { ISuggestionsProps } from './Suggestions.types';
import type { JSXElement } from '@fluentui/utilities';
export interface ISuggestionsState {
selectedActionType: SuggestionActionType;
}
/**
* {@docCategory Pickers}
*/
export declare class Suggestions<T> extends React.Component<ISuggestionsProps<T>, ISuggestionsState> {
protected _forceResolveButton: React.RefObject<IButton | null>;
protected _searchForMoreButton: React.RefObject<IButton | null>;
protected _selectedElement: React.RefObject<HTMLDivElement | null>;
protected _scrollContainer: React.RefObject<HTMLDivElement | null>;
private activeSelectedElement;
private _classNames;
constructor(suggestionsProps: ISuggestionsProps<T>);
componentDidMount(): void;
componentDidUpdate(): void;
render(): JSXElement;
/**
* Returns true if the event was handled, false otherwise
*/
tryHandleKeyDown: (keyCode: number, currentSuggestionIndex: number) => boolean;
hasSuggestedAction(): boolean;
hasSuggestedActionSelected(): boolean;
executeSelectedAction(): void;
focusAboveSuggestions(): void;
focusBelowSuggestions(): void;
focusSearchForMoreButton(): void;
scrollSelected(): void;
private _getAlertText;
private _renderSuggestions;
private _getMoreResults;
private _forceResolve;
private _shouldShowForceResolve;
private _onClickTypedSuggestionsItem;
private _refocusOnSuggestions;
private _onRemoveTypedSuggestionsItem;
}
@@ -0,0 +1,326 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Suggestions = void 0;
var tslib_1 = require("tslib");
var React = require("react");
var Utilities_1 = require("../../../Utilities");
var Button_1 = require("../../../Button");
var Spinner_1 = require("../../../Spinner");
var Announced_1 = require("../../../Announced");
var Suggestions_types_1 = require("./Suggestions.types");
var SuggestionsItem_1 = require("./SuggestionsItem");
var SuggestionsItem_styles_1 = require("./SuggestionsItem.styles");
var stylesImport = require("./Suggestions.scss");
var legacyStyles = stylesImport;
var getClassNames = (0, Utilities_1.classNamesFunction)();
var StyledSuggestionsItem = (0, Utilities_1.styled)(SuggestionsItem_1.SuggestionsItem, SuggestionsItem_styles_1.getStyles, undefined, {
scope: 'SuggestionItem',
});
/**
* {@docCategory Pickers}
*/
var Suggestions = /** @class */ (function (_super) {
tslib_1.__extends(Suggestions, _super);
function Suggestions(suggestionsProps) {
var _this = _super.call(this, suggestionsProps) || this;
_this._forceResolveButton = React.createRef();
_this._searchForMoreButton = React.createRef();
_this._selectedElement = React.createRef();
_this._scrollContainer = React.createRef();
/**
* Returns true if the event was handled, false otherwise
*/
_this.tryHandleKeyDown = function (keyCode, currentSuggestionIndex) {
var isEventHandled = false;
var newSelectedActionType = null;
var currentSelectedAction = _this.state.selectedActionType;
var suggestionLength = _this.props.suggestions.length;
if (keyCode === Utilities_1.KeyCodes.down) {
switch (currentSelectedAction) {
case Suggestions_types_1.SuggestionActionType.forceResolve:
if (suggestionLength > 0) {
_this._refocusOnSuggestions(keyCode);
newSelectedActionType = Suggestions_types_1.SuggestionActionType.none;
}
else if (_this._searchForMoreButton.current) {
newSelectedActionType = Suggestions_types_1.SuggestionActionType.searchMore;
}
else {
newSelectedActionType = Suggestions_types_1.SuggestionActionType.forceResolve;
}
break;
case Suggestions_types_1.SuggestionActionType.searchMore:
if (_this._forceResolveButton.current) {
newSelectedActionType = Suggestions_types_1.SuggestionActionType.forceResolve;
}
else if (suggestionLength > 0) {
_this._refocusOnSuggestions(keyCode);
newSelectedActionType = Suggestions_types_1.SuggestionActionType.none;
}
else {
newSelectedActionType = Suggestions_types_1.SuggestionActionType.searchMore;
}
break;
case Suggestions_types_1.SuggestionActionType.none:
if (currentSuggestionIndex === -1 && _this._forceResolveButton.current) {
newSelectedActionType = Suggestions_types_1.SuggestionActionType.forceResolve;
}
break;
}
}
else if (keyCode === Utilities_1.KeyCodes.up) {
switch (currentSelectedAction) {
case Suggestions_types_1.SuggestionActionType.forceResolve:
if (_this._searchForMoreButton.current) {
newSelectedActionType = Suggestions_types_1.SuggestionActionType.searchMore;
}
else if (suggestionLength > 0) {
_this._refocusOnSuggestions(keyCode);
newSelectedActionType = Suggestions_types_1.SuggestionActionType.none;
}
break;
case Suggestions_types_1.SuggestionActionType.searchMore:
if (suggestionLength > 0) {
_this._refocusOnSuggestions(keyCode);
newSelectedActionType = Suggestions_types_1.SuggestionActionType.none;
}
else if (_this._forceResolveButton.current) {
newSelectedActionType = Suggestions_types_1.SuggestionActionType.forceResolve;
}
break;
case Suggestions_types_1.SuggestionActionType.none:
if (currentSuggestionIndex === -1 && _this._searchForMoreButton.current) {
newSelectedActionType = Suggestions_types_1.SuggestionActionType.searchMore;
}
break;
}
}
if (newSelectedActionType !== null) {
_this.setState({ selectedActionType: newSelectedActionType });
isEventHandled = true;
}
return isEventHandled;
};
_this._getAlertText = function () {
var _a = _this.props, isLoading = _a.isLoading, isSearching = _a.isSearching, suggestions = _a.suggestions, suggestionsAvailableAlertText = _a.suggestionsAvailableAlertText, noResultsFoundText = _a.noResultsFoundText, isExtendedLoading = _a.isExtendedLoading, loadingText = _a.loadingText;
if (!isLoading && !isSearching) {
if (suggestions.length > 0) {
return suggestionsAvailableAlertText || '';
}
if (noResultsFoundText) {
return noResultsFoundText;
}
}
else if (isLoading && isExtendedLoading) {
return loadingText || '';
}
return '';
};
_this._getMoreResults = function () {
if (_this.props.onGetMoreResults) {
_this.props.onGetMoreResults();
// Reset selected action type as it will be of type SuggestionActionType.none after more results are gotten
_this.setState({ selectedActionType: Suggestions_types_1.SuggestionActionType.none });
}
};
_this._forceResolve = function () {
if (_this.props.createGenericItem) {
_this.props.createGenericItem();
}
};
_this._shouldShowForceResolve = function () {
return _this.props.showForceResolve ? _this.props.showForceResolve() : false;
};
_this._onClickTypedSuggestionsItem = function (item, index) {
return function (ev) {
_this.props.onSuggestionClick(ev, item, index);
};
};
_this._refocusOnSuggestions = function (keyCode) {
if (typeof _this.props.refocusSuggestions === 'function') {
_this.props.refocusSuggestions(keyCode);
}
};
_this._onRemoveTypedSuggestionsItem = function (item, index) {
return function (ev) {
var onSuggestionRemove = _this.props.onSuggestionRemove;
onSuggestionRemove(ev, item, index);
ev.stopPropagation();
};
};
(0, Utilities_1.initializeComponentRef)(_this);
_this.state = {
selectedActionType: Suggestions_types_1.SuggestionActionType.none,
};
return _this;
}
Suggestions.prototype.componentDidMount = function () {
this.scrollSelected();
this.activeSelectedElement = this._selectedElement ? this._selectedElement.current : null;
};
Suggestions.prototype.componentDidUpdate = function () {
// Only scroll to selected element if the selected element has changed. Otherwise do nothing.
// This prevents some odd behavior where scrolling the active element out of view and clicking on a selected element
// will trigger a focus event and not give the clicked element the click.
if (this._selectedElement.current && this.activeSelectedElement !== this._selectedElement.current) {
this.scrollSelected();
this.activeSelectedElement = this._selectedElement.current;
}
};
Suggestions.prototype.render = function () {
var _a, _b;
var _this = this;
var _c = this.props, forceResolveText = _c.forceResolveText, mostRecentlyUsedHeaderText = _c.mostRecentlyUsedHeaderText, searchForMoreIcon = _c.searchForMoreIcon, searchForMoreText = _c.searchForMoreText, className = _c.className, moreSuggestionsAvailable = _c.moreSuggestionsAvailable, noResultsFoundText = _c.noResultsFoundText, suggestions = _c.suggestions, isLoading = _c.isLoading, isSearching = _c.isSearching, loadingText = _c.loadingText, onRenderNoResultFound = _c.onRenderNoResultFound, searchingText = _c.searchingText, isMostRecentlyUsedVisible = _c.isMostRecentlyUsedVisible, resultsMaximumNumber = _c.resultsMaximumNumber, resultsFooterFull = _c.resultsFooterFull, resultsFooter = _c.resultsFooter, _d = _c.isResultsFooterVisible, isResultsFooterVisible = _d === void 0 ? true : _d, suggestionsHeaderText = _c.suggestionsHeaderText, suggestionsClassName = _c.suggestionsClassName, theme = _c.theme, styles = _c.styles, suggestionsListId = _c.suggestionsListId, suggestionsContainerAriaLabel = _c.suggestionsContainerAriaLabel;
// TODO
// Clean this up by leaving only the first part after removing support for SASS.
// Currently we can not remove the SASS styles from Suggestions class because it
// might be used by consumers separately from pickers extending from BasePicker
// and have not used the new 'styles' prop. Because it's expecting a type parameter,
// we can not use the 'styled' function without adding some helpers which can break
// downstream consumers who did not use the new helpers.
// We check for 'styles' prop which is going to be injected by the 'styled' HOC
// in BasePicker when the typed Suggestions class is ready to be rendered. If the check
// passes we can use the CSS-in-JS styles. If the check fails (ex: custom picker),
// then we just use the old SASS styles instead.
this._classNames = styles
? getClassNames(styles, {
theme: theme,
className: className,
suggestionsClassName: suggestionsClassName,
forceResolveButtonSelected: this.state.selectedActionType === Suggestions_types_1.SuggestionActionType.forceResolve,
searchForMoreButtonSelected: this.state.selectedActionType === Suggestions_types_1.SuggestionActionType.searchMore,
})
: {
root: (0, Utilities_1.css)('ms-Suggestions', className, legacyStyles.root),
title: (0, Utilities_1.css)('ms-Suggestions-title', legacyStyles.suggestionsTitle),
searchForMoreButton: (0, Utilities_1.css)('ms-SearchMore-button', legacyStyles.actionButton, (_a = {},
_a['is-selected ' + legacyStyles.buttonSelected] = this.state.selectedActionType === Suggestions_types_1.SuggestionActionType.searchMore,
_a)),
forceResolveButton: (0, Utilities_1.css)('ms-forceResolve-button', legacyStyles.actionButton, (_b = {},
_b['is-selected ' + legacyStyles.buttonSelected] = this.state.selectedActionType === Suggestions_types_1.SuggestionActionType.forceResolve,
_b)),
suggestionsAvailable: (0, Utilities_1.css)('ms-Suggestions-suggestionsAvailable', legacyStyles.suggestionsAvailable),
suggestionsContainer: (0, Utilities_1.css)('ms-Suggestions-container', legacyStyles.suggestionsContainer, suggestionsClassName),
noSuggestions: (0, Utilities_1.css)('ms-Suggestions-none', legacyStyles.suggestionsNone),
};
var spinnerStyles = this._classNames.subComponentStyles
? this._classNames.subComponentStyles.spinner
: undefined;
// TODO: cleanup after refactor of pickers to composition pattern and remove SASS support.
var spinnerClassNameOrStyles = styles
? { styles: spinnerStyles }
: {
className: (0, Utilities_1.css)('ms-Suggestions-spinner', legacyStyles.suggestionsSpinner),
};
var noResults = function () {
var defaultRender = function () {
return React.createElement("div", { className: _this._classNames.noSuggestions }, noResultsFoundText);
};
return (
// This ID can be used by the parent to set aria-activedescendant to this
React.createElement("div", { id: "sug-noResultsFound", role: "option" }, onRenderNoResultFound ? onRenderNoResultFound(undefined, defaultRender) : defaultRender()));
};
// MostRecently Used text should supercede the header text if it's there and available.
var headerText = suggestionsHeaderText;
if (isMostRecentlyUsedVisible && mostRecentlyUsedHeaderText) {
headerText = mostRecentlyUsedHeaderText;
}
var footerTitle = undefined;
if (isResultsFooterVisible) {
footerTitle = suggestions.length >= resultsMaximumNumber ? resultsFooterFull : resultsFooter;
}
var hasNoSuggestions = (!suggestions || !suggestions.length) && !isLoading;
var forceResolveId = this.state.selectedActionType === Suggestions_types_1.SuggestionActionType.forceResolve ? 'sug-selectedAction' : undefined;
var searchForMoreId = this.state.selectedActionType === Suggestions_types_1.SuggestionActionType.searchMore ? 'sug-selectedAction' : undefined;
return (React.createElement("div", { className: this._classNames.root, "aria-label": suggestionsContainerAriaLabel || headerText, id: suggestionsListId, role: "listbox" },
React.createElement(Announced_1.Announced, { message: this._getAlertText(), "aria-live": "polite" }),
headerText ? React.createElement("div", { className: this._classNames.title }, headerText) : null,
forceResolveText && this._shouldShowForceResolve() && (React.createElement(Button_1.CommandButton, { componentRef: this._forceResolveButton, className: this._classNames.forceResolveButton, id: forceResolveId, onClick: this._forceResolve, "data-automationid": 'sug-forceResolve' }, forceResolveText)),
isLoading && React.createElement(Spinner_1.Spinner, tslib_1.__assign({}, spinnerClassNameOrStyles, { ariaLabel: loadingText, label: loadingText })),
hasNoSuggestions ? noResults() : this._renderSuggestions(),
searchForMoreText && moreSuggestionsAvailable && (React.createElement(Button_1.CommandButton, { componentRef: this._searchForMoreButton, className: this._classNames.searchForMoreButton, iconProps: searchForMoreIcon || { iconName: 'Search' }, id: searchForMoreId, onClick: this._getMoreResults, "data-automationid": 'sug-searchForMore', role: 'option' }, searchForMoreText)),
isSearching ? React.createElement(Spinner_1.Spinner, tslib_1.__assign({}, spinnerClassNameOrStyles, { ariaLabel: searchingText, label: searchingText })) : null,
footerTitle && !moreSuggestionsAvailable && !isMostRecentlyUsedVisible && !isSearching ? (React.createElement("div", { className: this._classNames.title }, footerTitle(this.props))) : null));
};
Suggestions.prototype.hasSuggestedAction = function () {
return !!this._searchForMoreButton.current || !!this._forceResolveButton.current;
};
Suggestions.prototype.hasSuggestedActionSelected = function () {
return this.state.selectedActionType !== Suggestions_types_1.SuggestionActionType.none;
};
Suggestions.prototype.executeSelectedAction = function () {
switch (this.state.selectedActionType) {
case Suggestions_types_1.SuggestionActionType.forceResolve:
this._forceResolve();
break;
case Suggestions_types_1.SuggestionActionType.searchMore:
this._getMoreResults();
break;
}
};
Suggestions.prototype.focusAboveSuggestions = function () {
if (this._forceResolveButton.current) {
this.setState({ selectedActionType: Suggestions_types_1.SuggestionActionType.forceResolve });
}
else if (this._searchForMoreButton.current) {
this.setState({ selectedActionType: Suggestions_types_1.SuggestionActionType.searchMore });
}
};
Suggestions.prototype.focusBelowSuggestions = function () {
if (this._searchForMoreButton.current) {
this.setState({ selectedActionType: Suggestions_types_1.SuggestionActionType.searchMore });
}
else if (this._forceResolveButton.current) {
this.setState({ selectedActionType: Suggestions_types_1.SuggestionActionType.forceResolve });
}
};
Suggestions.prototype.focusSearchForMoreButton = function () {
if (this._searchForMoreButton.current) {
this._searchForMoreButton.current.focus();
}
};
Suggestions.prototype.scrollSelected = function () {
if (this._selectedElement.current &&
this._scrollContainer.current &&
this._scrollContainer.current.scrollTo !== undefined) {
var _a = this._selectedElement.current, offsetHeight = _a.offsetHeight, offsetTop = _a.offsetTop;
var _b = this._scrollContainer.current, parentOffsetHeight = _b.offsetHeight, scrollTop = _b.scrollTop;
var isAbove = offsetTop < scrollTop;
var isBelow = offsetTop + offsetHeight > scrollTop + parentOffsetHeight;
if (isAbove) {
this._scrollContainer.current.scrollTo(0, offsetTop);
}
else if (isBelow) {
this._scrollContainer.current.scrollTo(0, offsetTop - parentOffsetHeight + offsetHeight);
}
}
};
Suggestions.prototype._renderSuggestions = function () {
var _this = this;
var _a = this.props, onRenderSuggestion = _a.onRenderSuggestion, removeSuggestionAriaLabel = _a.removeSuggestionAriaLabel, suggestionsItemClassName = _a.suggestionsItemClassName, resultsMaximumNumber = _a.resultsMaximumNumber, showRemoveButtons = _a.showRemoveButtons, removeButtonIconProps = _a.removeButtonIconProps;
var suggestions = this.props.suggestions;
var StyledTypedSuggestionsItem = StyledSuggestionsItem;
var selectedIndex = -1;
suggestions.some(function (element, index) {
if (element.selected) {
selectedIndex = index;
return true;
}
return false;
});
if (resultsMaximumNumber) {
suggestions =
selectedIndex >= resultsMaximumNumber
? suggestions.slice(selectedIndex - resultsMaximumNumber + 1, selectedIndex + 1)
: suggestions.slice(0, resultsMaximumNumber);
}
if (suggestions.length === 0) {
return null;
}
return (React.createElement("div", { className: this._classNames.suggestionsContainer, ref: this._scrollContainer, role: "presentation" }, suggestions.map(function (suggestion, index) { return (React.createElement("div", { ref: suggestion.selected ? _this._selectedElement : undefined, key: suggestion.item.key ? suggestion.item.key : index, role: "presentation" },
React.createElement(StyledTypedSuggestionsItem, { suggestionModel: suggestion, RenderSuggestion: onRenderSuggestion, onClick: _this._onClickTypedSuggestionsItem(suggestion.item, index), className: suggestionsItemClassName, showRemoveButton: showRemoveButtons, removeButtonAriaLabel: removeSuggestionAriaLabel, onRemoveItem: _this._onRemoveTypedSuggestionsItem(suggestion.item, index), id: 'sug-' + index, removeButtonIconProps: removeButtonIconProps }))); })));
};
return Suggestions;
}(React.Component));
exports.Suggestions = Suggestions;
//# sourceMappingURL=Suggestions.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,12 @@
export declare const root = "root_8c91000a";
export declare const suggestionsItem = "suggestionsItem_8c91000a";
export declare const closeButton = "closeButton_8c91000a";
export declare const suggestionsItemIsSuggested = "suggestionsItemIsSuggested_8c91000a";
export declare const itemButton = "itemButton_8c91000a";
export declare const actionButton = "actionButton_8c91000a";
export declare const buttonSelected = "buttonSelected_8c91000a";
export declare const suggestionsTitle = "suggestionsTitle_8c91000a";
export declare const suggestionsContainer = "suggestionsContainer_8c91000a";
export declare const suggestionsNone = "suggestionsNone_8c91000a";
export declare const suggestionsSpinner = "suggestionsSpinner_8c91000a";
export declare const suggestionsAvailable = "suggestionsAvailable_8c91000a";
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,2 @@
import type { ISuggestionsStyleProps, ISuggestionsStyles } from './Suggestions.types';
export declare function getStyles(props: ISuggestionsStyleProps): ISuggestionsStyles;
@@ -0,0 +1,144 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getStyles = getStyles;
var tslib_1 = require("tslib");
var Styling_1 = require("../../../Styling");
var GlobalClassNames = {
root: 'ms-Suggestions',
suggestionsContainer: 'ms-Suggestions-container',
title: 'ms-Suggestions-title',
forceResolveButton: 'ms-forceResolve-button',
searchForMoreButton: 'ms-SearchMore-button',
spinner: 'ms-Suggestions-spinner',
noSuggestions: 'ms-Suggestions-none',
suggestionsAvailable: 'ms-Suggestions-suggestionsAvailable',
isSelected: 'is-selected',
};
function getStyles(props) {
var _a;
var className = props.className, suggestionsClassName = props.suggestionsClassName, theme = props.theme, forceResolveButtonSelected = props.forceResolveButtonSelected, searchForMoreButtonSelected = props.searchForMoreButtonSelected;
var palette = theme.palette, semanticColors = theme.semanticColors, fonts = theme.fonts;
var classNames = (0, Styling_1.getGlobalClassNames)(GlobalClassNames, theme);
var actionButtonStyles = {
backgroundColor: 'transparent',
border: 0,
cursor: 'pointer',
margin: 0,
paddingLeft: 8,
position: 'relative',
borderTop: "1px solid ".concat(palette.neutralLight),
height: 40,
textAlign: 'left',
width: '100%',
fontSize: fonts.small.fontSize,
selectors: {
':hover': {
backgroundColor: semanticColors.menuItemBackgroundPressed,
cursor: 'pointer',
},
':focus, :active': {
backgroundColor: palette.themeLight,
},
'.ms-Button-icon': {
fontSize: fonts.mediumPlus.fontSize,
width: 25,
},
'.ms-Button-label': {
margin: '0 4px 0 9px',
},
},
};
var actionButtonSelectedStyles = {
backgroundColor: palette.themeLight,
selectors: (_a = {},
_a[Styling_1.HighContrastSelector] = tslib_1.__assign({ backgroundColor: 'Highlight', borderColor: 'Highlight', color: 'HighlightText' }, (0, Styling_1.getHighContrastNoAdjustStyle)()),
_a[':after'] = {
pointerEvents: 'none',
content: '""',
position: 'absolute',
left: 0,
top: 0,
bottom: 0,
right: 0,
border: "1px solid ".concat(theme.semanticColors.focusBorder),
},
_a),
};
return {
root: [
classNames.root,
{
display: 'flex',
flexDirection: 'column',
minWidth: 260,
maxHeight: '100%',
},
className,
],
suggestionsContainer: [
classNames.suggestionsContainer,
{
overflowY: 'auto',
overflowX: 'hidden',
maxHeight: 300,
transform: 'translate3d(0,0,0)',
},
suggestionsClassName,
],
title: [
classNames.title,
{
padding: '0 12px',
fontSize: fonts.small.fontSize,
color: palette.themePrimary,
lineHeight: 40,
borderBottom: "1px solid ".concat(semanticColors.menuItemBackgroundPressed),
},
],
forceResolveButton: [
classNames.forceResolveButton,
actionButtonStyles,
forceResolveButtonSelected && [classNames.isSelected, actionButtonSelectedStyles],
],
searchForMoreButton: [
classNames.searchForMoreButton,
actionButtonStyles,
searchForMoreButtonSelected && [classNames.isSelected, actionButtonSelectedStyles],
],
noSuggestions: [
classNames.noSuggestions,
{
textAlign: 'center',
color: palette.neutralSecondary,
fontSize: fonts.small.fontSize,
lineHeight: 30,
},
],
suggestionsAvailable: [classNames.suggestionsAvailable, Styling_1.hiddenContentStyle],
subComponentStyles: {
spinner: {
root: [
classNames.spinner,
{
margin: '5px 0',
paddingLeft: 14,
textAlign: 'left',
whiteSpace: 'nowrap',
lineHeight: 20,
fontSize: fonts.small.fontSize,
},
],
circle: {
display: 'inline-block',
verticalAlign: 'middle',
},
label: {
display: 'inline-block',
verticalAlign: 'middle',
margin: '0 10px 0 16px',
},
},
},
};
}
//# sourceMappingURL=Suggestions.styles.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,264 @@
import * as React from 'react';
import { KeyCodes } from '../../../Utilities';
import type { IReactProps, IRefObject, IRenderFunction, IStyleFunctionOrObject } from '../../../Utilities';
import type { IPersonaProps } from '../../Persona/Persona.types';
import type { IStyle, ITheme } from '../../../Styling';
import type { ISpinnerStyleProps } from '../../Spinner/Spinner.types';
import type { ISuggestionItemProps } from './SuggestionsItem.types';
import { IIconProps } from '../../Icon/Icon.types';
import type { JSXElement } from '@fluentui/utilities';
/**
* Suggestions component.
* {@docCategory Pickers}
*/
export interface ISuggestions<T> {
/** Execute the action selected. Can be SearchMore or ForceResolve actions. */
executeSelectedAction: () => void;
/** Focus on the ForceResolve action above the suggestions. If not available then focus on SearchMore action. */
focusAboveSuggestions: () => void;
/** Focus on the SearchMore action below the suggestions. If not available then focus on ForceResolve action. */
focusBelowSuggestions: () => void;
/** Focus the SearchMore action button. */
focusSearchForMoreButton: () => void;
/** Whether it has any suggested actions like ForceResolve or SearchMore. */
hasSuggestedAction: () => boolean;
/** Whether any of the suggested actions (ForceResolve or SearchMore) is selected. */
hasSuggestedActionSelected: () => boolean;
/** Returns true if the event was handled, false otherwise. */
tryHandleKeyDown: (keyCode: number, currentSuggestionIndex: number) => boolean;
}
/**
* Suggestions props interface. Refers to the entire container holding all the suggestions.
* Type T is the type of the items that are displayed.
* {@docCategory Pickers}
*/
export interface ISuggestionsProps<T> extends IReactProps<any> {
/**
* Optional callback to access the ISuggestions interface. Use this instead of ref for accessing
* the public methods and properties of the component.
*/
componentRef?: IRefObject<ISuggestions<T>>;
/**
* How the suggestion should look in the suggestion list.
*/
onRenderSuggestion: (props: T, suggestionItemProps: ISuggestionItemProps<T>) => JSXElement;
/**
* What should occur when a suggestion is clicked
*/
onSuggestionClick: (ev?: React.MouseEvent<HTMLElement>, item?: any, index?: number) => void;
/**
* The list of Suggestions that will be displayed
*/
suggestions: ISuggestionModel<T>[];
/**
* How the "no result found" should look in the suggestion list.
*/
onRenderNoResultFound?: IRenderFunction<void>;
/**
* The text that appears at the top of the suggestions list.
*/
suggestionsHeaderText?: string;
/**
* The text that should appear at the top of the most recently used box.
*/
mostRecentlyUsedHeaderText?: string;
/**
* The icon that appears indicating to the user that they can search for more results.
*/
searchForMoreIcon?: IIconProps;
/**
* The text that appears indicating to the user that they can search for more results.
*/
searchForMoreText?: string;
/**
* The callback that should be called when the user attempts to get more results
*/
onGetMoreResults?: () => void;
/**
* The text that appears indicating to the use to force resolve the input
*/
forceResolveText?: string;
/**
* The callback that should be called to see if the force resolve command should be shown
*/
showForceResolve?: () => boolean;
/**
* The callback that should be called when the user attempts to use the input text as as item
*/
createGenericItem?: () => void;
/**
* The CSS className of the suggestions root.
*/
className?: string;
/**
* The CSS className of the suggestions list
*/
suggestionsClassName?: string;
/**
* The text that should appear if there is a search error.
*
* @deprecated Use noResultsFoundText instead.
*/
searchErrorText?: string;
/**
* The text that should appear if no results are found when searching.
*/
noResultsFoundText?: string;
/**
* The className of the suggestion item.
*/
suggestionsItemClassName?: string;
/**
* Used to indicate whether or not the user can request more suggestions.
* Dictates whether or not the searchForMore button is displayed.
*/
moreSuggestionsAvailable?: boolean;
/**
* Used to indicate whether or not the suggestions are loading.
*/
isLoading?: boolean;
/**
* Used to indicate whether or not the suggestions are taking an extended amount of time to load.
*/
isExtendedLoading?: boolean;
/**
* Used to indicate whether or not the component is searching for more results.
*/
isSearching?: boolean;
/**
* The text to display while the results are loading.
*/
loadingText?: string;
/**
* The text to display while searching for more results in a limited suggestions list.
*/
searchingText?: string;
/**
* Indicates if a short list of recent suggestions should be shown.
*/
isMostRecentlyUsedVisible?: boolean;
/**
* Function to fire when one of the optional remove buttons on a suggestion is clicked.
*
* TODO (adjective-object) remove IPersonaprops before the next major version bump
*/
onSuggestionRemove?: (ev?: React.MouseEvent<HTMLElement>, item?: T | IPersonaProps, index?: number) => void;
/**
* Indicates if the text in resultsFooter or resultsFooterFull should be shown at the end of the suggestion list.
* @defaultvalue true
*/
isResultsFooterVisible?: boolean;
/**
* Maximum number of suggestions to show in the full suggestion list.
*/
resultsMaximumNumber?: number;
/**
* A renderer that adds an element at the end of the suggestions list it has more items than resultsMaximumNumber.
* This should not include interactive elements as the footer is not focusable.
*/
resultsFooterFull?: (props: ISuggestionsProps<T>) => JSXElement;
/**
* A renderer that adds an element at the end of the suggestions list it has fewer items than resultsMaximumNumber.
* This should not include interactive elements as the footer is not focusable.
*/
resultsFooter?: (props: ISuggestionsProps<T>) => JSXElement;
/**
* Indicates whether to show a button with each suggestion to remove that suggestion.
*/
showRemoveButtons?: boolean;
/**
* Screen reader message to read when there are suggestions available.
*/
suggestionsAvailableAlertText?: string;
/**
* A function that resets focus to the expected item in the suggestion list
*/
refocusSuggestions?: (keyCode: KeyCodes) => void;
/**
* An ARIA label for the container that is the parent of the suggestions.
*/
suggestionsContainerAriaLabel?: string;
/**
* An ARIA label to use for the buttons to remove individual suggestions.
*/
removeSuggestionAriaLabel?: string;
/**
* The string that will be used as the suggestionsListId.
* Will be used by the BasePicker to keep track of the list for aria.
*/
suggestionsListId?: string;
/** Call to provide customized styling that will layer on top of the variant rules. */
styles?: IStyleFunctionOrObject<any, any>;
/** Theme provided by High-Order Component. */
theme?: ITheme;
/**
* Props for the icon used in the item's remove button.
* @defaultvalue `{ iconName:'Cancel' }`
*/
removeButtonIconProps?: IIconProps;
}
/**
* The props needed to construct Suggestions styles.
* {@docCategory Pickers}
*/
export type ISuggestionsStyleProps = Required<Pick<ISuggestionsProps<any>, 'theme'>> & Pick<ISuggestionsProps<any>, 'className' | 'suggestionsClassName'> & {
/** Whether the forceResolve actionButton is selected. */
forceResolveButtonSelected?: boolean;
/** Whether the searchForMore actionButton is selected. */
searchForMoreButtonSelected?: boolean;
};
/**
* Represents the stylable areas of the Suggestions.
* {@docCategory Pickers}
*/
export interface ISuggestionsStyles {
/** Root element of the suggestions outer wrapper. */
root: IStyle;
/** Refers to the suggestions container. */
suggestionsContainer: IStyle;
/** Refers to the title rendered for suggestions container header and/or footer (if provided). */
title: IStyle;
/** Refers to the 'Force resolve' actionButton. */
forceResolveButton: IStyle;
/** Refers to the 'Search for more' actionButton. */
searchForMoreButton: IStyle;
/** Refers to the text rendered when no suggestions are found. */
noSuggestions: IStyle;
/** Refers to the text displaying if more suggestions available. */
suggestionsAvailable: IStyle;
/** SubComponents (Spinner) styles. */
subComponentStyles: ISuggestionsSubComponentStyles;
}
/**
* Styles interface of the SubComponents rendered within PeoplePickerItemSelected.
* {@docCategory Pickers}
*/
export interface ISuggestionsSubComponentStyles {
/** Refers to the Spinner rendered within the Suggestions when searching or loading suggestions. */
spinner: IStyleFunctionOrObject<ISpinnerStyleProps, any>;
}
/**
* SuggestionModel interface.
* Type T is the type of the item that is suggested (Persona, Tag or any other custom picker).
* {@docCategory Pickers}
*/
export interface ISuggestionModel<T> {
/** The suggested item of the type T */
item: T;
/** Whether the suggested item is selected or not. */
selected: boolean;
/** Aria-label string for each suggested item. */
ariaLabel?: string;
}
/**
* Enum to help identify which suggestions action button is selected.
* {@docCategory Pickers}
*/
export declare enum SuggestionActionType {
/** None of the actions is selected. */
none = 0,
/** ForceResolve action is selected. */
forceResolve = 1,
/** SearchMore action is selected. */
searchMore = 2
}
@@ -0,0 +1,17 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SuggestionActionType = void 0;
/**
* Enum to help identify which suggestions action button is selected.
* {@docCategory Pickers}
*/
var SuggestionActionType;
(function (SuggestionActionType) {
/** None of the actions is selected. */
SuggestionActionType[SuggestionActionType["none"] = 0] = "none";
/** ForceResolve action is selected. */
SuggestionActionType[SuggestionActionType["forceResolve"] = 1] = "forceResolve";
/** SearchMore action is selected. */
SuggestionActionType[SuggestionActionType["searchMore"] = 2] = "searchMore";
})(SuggestionActionType || (exports.SuggestionActionType = SuggestionActionType = {}));
//# sourceMappingURL=Suggestions.types.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,30 @@
import type { ISuggestionModel } from './Suggestions.types';
/**
* {@docCategory Pickers}
*/
export declare class SuggestionsController<T> {
currentIndex: number;
currentSuggestion: ISuggestionModel<T> | undefined;
suggestions: ISuggestionModel<T>[];
constructor();
updateSuggestions(newSuggestions: T[], selectedIndex?: number, maxCount?: number): void;
/**
* Increments the suggestion index and gets the next suggestion in the list.
*/
nextSuggestion(): boolean;
/**
* Decrements the suggestion index and gets the previous suggestion in the list.
*/
previousSuggestion(): boolean;
getSuggestions(): ISuggestionModel<T>[];
getCurrentItem(): ISuggestionModel<T>;
getSuggestionAtIndex(index: number): ISuggestionModel<T>;
hasSelectedSuggestion(): boolean;
removeSuggestion(index: number): void;
createGenericSuggestion(itemToConvert: ISuggestionModel<T> | T): void;
convertSuggestionsToSuggestionItems(suggestions: Array<ISuggestionModel<T> | T>): ISuggestionModel<T>[];
deselectAllSuggestions(): void;
setSelectedSuggestion(index: number): void;
private _isSuggestionModel;
private _ensureSuggestionModel;
}
@@ -0,0 +1,129 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SuggestionsController = void 0;
/**
* {@docCategory Pickers}
*/
var SuggestionsController = /** @class */ (function () {
function SuggestionsController() {
var _this = this;
this._isSuggestionModel = function (value) {
return value.item !== undefined;
};
this._ensureSuggestionModel = function (suggestion) {
if (_this._isSuggestionModel(suggestion)) {
return suggestion;
}
else {
return {
item: suggestion,
selected: false,
ariaLabel: suggestion.ariaLabel,
};
}
};
this.suggestions = [];
this.currentIndex = -1;
}
SuggestionsController.prototype.updateSuggestions = function (newSuggestions, selectedIndex, maxCount) {
if (newSuggestions && newSuggestions.length > 0) {
if (maxCount && newSuggestions.length > maxCount) {
var startIndex = selectedIndex && selectedIndex > maxCount ? selectedIndex + 1 - maxCount : 0;
newSuggestions = newSuggestions.slice(startIndex, startIndex + maxCount - 1);
}
this.suggestions = this.convertSuggestionsToSuggestionItems(newSuggestions);
this.currentIndex = selectedIndex ? selectedIndex : 0;
if (selectedIndex === -1) {
this.currentSuggestion = undefined;
}
else if (selectedIndex !== undefined) {
this.suggestions[selectedIndex].selected = true;
this.currentSuggestion = this.suggestions[selectedIndex];
}
}
else {
this.suggestions = [];
this.currentIndex = -1;
this.currentSuggestion = undefined;
}
};
/**
* Increments the suggestion index and gets the next suggestion in the list.
*/
SuggestionsController.prototype.nextSuggestion = function () {
if (this.suggestions && this.suggestions.length) {
if (this.currentIndex < this.suggestions.length - 1) {
this.setSelectedSuggestion(this.currentIndex + 1);
return true;
}
else if (this.currentIndex === this.suggestions.length - 1) {
this.setSelectedSuggestion(0);
return true;
}
}
return false;
};
/**
* Decrements the suggestion index and gets the previous suggestion in the list.
*/
SuggestionsController.prototype.previousSuggestion = function () {
if (this.suggestions && this.suggestions.length) {
if (this.currentIndex > 0) {
this.setSelectedSuggestion(this.currentIndex - 1);
return true;
}
else if (this.currentIndex === 0) {
this.setSelectedSuggestion(this.suggestions.length - 1);
return true;
}
}
return false;
};
SuggestionsController.prototype.getSuggestions = function () {
return this.suggestions;
};
SuggestionsController.prototype.getCurrentItem = function () {
return this.currentSuggestion;
};
SuggestionsController.prototype.getSuggestionAtIndex = function (index) {
return this.suggestions[index];
};
SuggestionsController.prototype.hasSelectedSuggestion = function () {
return this.currentSuggestion ? true : false;
};
SuggestionsController.prototype.removeSuggestion = function (index) {
this.suggestions.splice(index, 1);
};
SuggestionsController.prototype.createGenericSuggestion = function (itemToConvert) {
var itemToAdd = this.convertSuggestionsToSuggestionItems([itemToConvert])[0];
this.currentSuggestion = itemToAdd;
};
SuggestionsController.prototype.convertSuggestionsToSuggestionItems = function (suggestions) {
return Array.isArray(suggestions) ? suggestions.map(this._ensureSuggestionModel) : [];
};
SuggestionsController.prototype.deselectAllSuggestions = function () {
if (this.currentIndex > -1) {
this.suggestions[this.currentIndex].selected = false;
this.currentIndex = -1;
}
};
SuggestionsController.prototype.setSelectedSuggestion = function (index) {
if (index > this.suggestions.length - 1 || index < 0) {
this.currentIndex = 0;
this.currentSuggestion.selected = false;
this.currentSuggestion = this.suggestions[0];
this.currentSuggestion.selected = true;
}
else {
if (this.currentIndex > -1) {
this.suggestions[this.currentIndex].selected = false;
}
this.suggestions[index].selected = true;
this.currentIndex = index;
this.currentSuggestion = this.suggestions[index];
}
};
return SuggestionsController;
}());
exports.SuggestionsController = SuggestionsController;
//# sourceMappingURL=SuggestionsController.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,10 @@
import * as React from 'react';
import type { ISuggestionItemProps } from './SuggestionsItem.types';
import type { JSXElement } from '@fluentui/utilities';
/**
* {@docCategory Pickers}
*/
export declare class SuggestionsItem<T> extends React.Component<ISuggestionItemProps<T>, {}> {
constructor(props: ISuggestionItemProps<T>);
render(): JSXElement;
}
@@ -0,0 +1,55 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SuggestionsItem = void 0;
var tslib_1 = require("tslib");
var React = require("react");
var Utilities_1 = require("../../../Utilities");
var Button_1 = require("../../../Button");
var stylesImport = require("./Suggestions.scss");
var legacyStyles = stylesImport;
var getClassNames = (0, Utilities_1.classNamesFunction)();
/**
* {@docCategory Pickers}
*/
var SuggestionsItem = /** @class */ (function (_super) {
tslib_1.__extends(SuggestionsItem, _super);
function SuggestionsItem(props) {
var _this = _super.call(this, props) || this;
(0, Utilities_1.initializeComponentRef)(_this);
return _this;
}
SuggestionsItem.prototype.render = function () {
var _a;
var _b = this.props, suggestionModel = _b.suggestionModel, RenderSuggestion = _b.RenderSuggestion, onClick = _b.onClick, className = _b.className, id = _b.id, onRemoveItem = _b.onRemoveItem, isSelectedOverride = _b.isSelectedOverride, removeButtonAriaLabel = _b.removeButtonAriaLabel, styles = _b.styles, theme = _b.theme, removeButtonIconProps = _b.removeButtonIconProps;
// TODO
// Clean this up by leaving only the first part after removing support for SASS.
// Currently we can not remove the SASS styles from SuggestionsItem class because it
// might be used by consumers separately from pickers extending from BasePicker
// and have not used the new 'styles' prop. Because it's expecting a type parameter,
// we can not use the 'styled' function without adding some helpers which can break
// downstream consumers who did not use the new helpers.
// We check for 'styles' prop which is going to be injected by the 'styled' HOC
// in Suggestions when the typed SuggestionsItem class is ready to be rendered. If the
// check passes we can use the CSS-in-JS styles. If the check fails (ex: custom picker),
// then we just use the old SASS styles instead.
var classNames = styles
? getClassNames(styles, {
theme: theme,
className: className,
suggested: suggestionModel.selected || isSelectedOverride,
})
: {
root: (0, Utilities_1.css)('ms-Suggestions-item', legacyStyles.suggestionsItem, (_a = {},
_a['is-suggested ' + legacyStyles.suggestionsItemIsSuggested] = suggestionModel.selected || isSelectedOverride,
_a), className),
itemButton: (0, Utilities_1.css)('ms-Suggestions-itemButton', legacyStyles.itemButton),
closeButton: (0, Utilities_1.css)('ms-Suggestions-closeButton', legacyStyles.closeButton),
};
return (React.createElement("div", { className: classNames.root, role: "presentation" },
React.createElement(Button_1.CommandButton, { onClick: onClick, className: classNames.itemButton, id: id, "aria-selected": suggestionModel.selected, role: "option", "aria-label": suggestionModel.ariaLabel }, RenderSuggestion(suggestionModel.item, this.props)),
this.props.showRemoveButton ? (React.createElement(Button_1.IconButton, { iconProps: removeButtonIconProps !== null && removeButtonIconProps !== void 0 ? removeButtonIconProps : { iconName: 'Cancel' }, styles: { icon: { fontSize: '12px' } }, title: removeButtonAriaLabel, ariaLabel: removeButtonAriaLabel, onClick: onRemoveItem, className: classNames.closeButton })) : null));
};
return SuggestionsItem;
}(React.Component));
exports.SuggestionsItem = SuggestionsItem;
//# sourceMappingURL=SuggestionsItem.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,8 @@
import type { ISuggestionsItemStyleProps, ISuggestionsItemStyles } from './SuggestionsItem.types';
export declare const SuggestionsItemGlobalClassNames: {
root: string;
itemButton: string;
closeButton: string;
isSuggested: string;
};
export declare function getStyles(props: ISuggestionsItemStyleProps): ISuggestionsItemStyles;
@@ -0,0 +1,140 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SuggestionsItemGlobalClassNames = void 0;
exports.getStyles = getStyles;
var tslib_1 = require("tslib");
var Styling_1 = require("../../../Styling");
var Utilities_1 = require("../../../Utilities");
exports.SuggestionsItemGlobalClassNames = {
root: 'ms-Suggestions-item',
itemButton: 'ms-Suggestions-itemButton',
closeButton: 'ms-Suggestions-closeButton',
isSuggested: 'is-suggested',
};
function getStyles(props) {
var _a, _b, _c, _d, _e, _f;
var className = props.className, theme = props.theme, suggested = props.suggested;
var palette = theme.palette, semanticColors = theme.semanticColors;
var classNames = (0, Styling_1.getGlobalClassNames)(exports.SuggestionsItemGlobalClassNames, theme);
return {
root: [
classNames.root,
{
display: 'flex',
alignItems: 'stretch',
boxSizing: 'border-box',
width: '100%',
position: 'relative',
selectors: {
'&:hover': {
background: semanticColors.menuItemBackgroundHovered,
},
'&:hover .ms-Suggestions-closeButton': {
display: 'block',
},
},
},
suggested && {
selectors: (_a = {},
_a[".".concat(Utilities_1.IsFocusVisibleClassName, " &, :host(.").concat(Utilities_1.IsFocusVisibleClassName, ") &")] = {
selectors: (_b = {},
_b[".".concat(classNames.closeButton)] = {
display: 'block',
background: semanticColors.menuItemBackgroundPressed,
},
_b),
},
_a[':after'] = {
pointerEvents: 'none',
content: '""',
position: 'absolute',
left: 0,
top: 0,
bottom: 0,
right: 0,
border: "1px solid ".concat(theme.semanticColors.focusBorder),
},
_a),
},
className,
],
itemButton: [
classNames.itemButton,
{
justifyContent: 'flex-start',
width: '100%',
padding: 0,
border: 'none',
height: '100%',
// Force the item button to be collapsible so it can always shrink
// to accommodate the close button as a peer in its flex container.
minWidth: 0,
// Required for IE11 to truncate the component.
overflow: 'hidden',
selectors: (_c = {},
_c[Styling_1.HighContrastSelector] = {
color: 'WindowText',
selectors: {
':hover': tslib_1.__assign({ background: 'Highlight', color: 'HighlightText' }, (0, Styling_1.getHighContrastNoAdjustStyle)()),
},
},
_c[':hover'] = {
color: semanticColors.menuItemTextHovered,
},
_c['.ms-Button-flexContainer'] = {
width: '100%',
},
_c),
},
suggested && [
classNames.isSuggested,
{
background: semanticColors.menuItemBackgroundPressed,
selectors: (_d = {
':hover': {
background: semanticColors.menuDivider,
}
},
_d[Styling_1.HighContrastSelector] = tslib_1.__assign({ background: 'Highlight', color: 'HighlightText' }, (0, Styling_1.getHighContrastNoAdjustStyle)()),
_d),
},
],
],
closeButton: [
classNames.closeButton,
{
display: 'none',
color: palette.neutralSecondary,
padding: '0 4px',
height: 'auto',
width: 32,
selectors: (_e = {
':hover, :active': {
background: palette.neutralTertiaryAlt,
color: palette.neutralDark,
}
},
_e[Styling_1.HighContrastSelector] = {
color: 'WindowText',
},
_e),
},
suggested && (_f = {},
_f[".".concat(Utilities_1.IsFocusVisibleClassName, " &, :host(.").concat(Utilities_1.IsFocusVisibleClassName, ") &")] = {
selectors: {
':hover, :active': {
background: palette.neutralTertiary,
},
},
},
_f.selectors = {
':hover, :active': {
background: palette.neutralTertiary,
color: palette.neutralPrimary,
},
},
_f),
],
};
}
//# sourceMappingURL=SuggestionsItem.styles.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,73 @@
import * as React from 'react';
import type { IStyle, ITheme } from '../../../Styling';
import type { IRefObject, IStyleFunctionOrObject } from '../../../Utilities';
import type { ISuggestionModel } from './Suggestions.types';
import { IIconProps } from '../../Icon/Icon.types';
import type { JSXElement } from '@fluentui/utilities';
/**
* SuggestionItem component.
* {@docCategory Pickers}
*/
export interface ISuggestionsItem {
}
/**
* Suggestion item props. Refers to the each individual suggested items rendered within Suggestions callout.
* Type T is the type of the item that is displayed.
* {@docCategory Pickers}
*/
export interface ISuggestionItemProps<T> {
/**
* Optional callback to access the ISuggestionItem interface. Use this instead of ref for accessing
* the public methods and properties of the component.
*/
componentRef?: IRefObject<ISuggestionsItem>;
/** Individual suggestion object containing its properties. */
suggestionModel: ISuggestionModel<T>;
/** Optional renderer to override the default one for each type of picker. */
RenderSuggestion: (item: T, suggestionItemProps: ISuggestionItemProps<T>) => JSXElement;
/** Callback for when the user clicks on the suggestion. */
onClick: (ev: React.MouseEvent<HTMLButtonElement>) => void;
/** Callback for when the item is removed from the array of suggested items. */
onRemoveItem: (ev: React.MouseEvent<HTMLButtonElement>) => void;
/** Optional className for the root element of the suggestion item. */
className?: string;
/** Unique id of the suggested item. */
id?: string;
/** Whether the remove button should be rendered or not. */
showRemoveButton?: boolean;
/** An override for the 'selected' property of the SuggestionModel. */
isSelectedOverride?: boolean;
/**
* The ARIA label for the button to remove the suggestion from the list.
*/
removeButtonAriaLabel?: string;
/** Call to provide customized styling that will layer on top of the variant rules. */
styles?: IStyleFunctionOrObject<ISuggestionsItemStyleProps, ISuggestionsItemStyles>;
/** Theme provided by High-Order Component. */
theme?: ITheme;
/**
* Props for the icon used in the item's remove button.
* @defaultvalue `{ iconName:'Cancel' }`
*/
removeButtonIconProps?: IIconProps;
}
/**
* The props needed to construct SuggestionItem styles.
* {@docCategory Pickers}
*/
export type ISuggestionsItemStyleProps = Required<Pick<ISuggestionItemProps<any>, 'theme'>> & Pick<ISuggestionItemProps<any>, 'className'> & {
/** Whether the suggestion item is selected or not. */
suggested?: boolean;
};
/**
* Represents the stylable areas of the SuggestionItem.
* {@docCategory Pickers}
*/
export interface ISuggestionsItemStyles {
/** Root element of the suggested item. */
root: IStyle;
/** Refers to the CommandButton holding the content of the suggested item. */
itemButton: IStyle;
/** Refers to the remove button in case it's rendered. */
closeButton: IStyle;
}
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=SuggestionsItem.types.js.map
@@ -0,0 +1 @@
{"version":3,"file":"SuggestionsItem.types.js","sourceRoot":"../src/","sources":["components/pickers/Suggestions/SuggestionsItem.types.ts"],"names":[],"mappings":"","sourcesContent":["import * as React from 'react';\nimport type { IStyle, ITheme } from '../../../Styling';\nimport type { IRefObject, IStyleFunctionOrObject } from '../../../Utilities';\nimport type { ISuggestionModel } from './Suggestions.types';\nimport { IIconProps } from '../../Icon/Icon.types';\nimport type { JSXElement } from '@fluentui/utilities';\n/**\n * SuggestionItem component.\n * {@docCategory Pickers}\n */\nexport interface ISuggestionsItem {}\n\n/**\n * Suggestion item props. Refers to the each individual suggested items rendered within Suggestions callout.\n * Type T is the type of the item that is displayed.\n * {@docCategory Pickers}\n */\nexport interface ISuggestionItemProps<T> {\n /**\n * Optional callback to access the ISuggestionItem interface. Use this instead of ref for accessing\n * the public methods and properties of the component.\n */\n componentRef?: IRefObject<ISuggestionsItem>;\n\n /** Individual suggestion object containing its properties. */\n suggestionModel: ISuggestionModel<T>;\n\n /** Optional renderer to override the default one for each type of picker. */\n // eslint-disable-next-line @typescript-eslint/naming-convention\n RenderSuggestion: (item: T, suggestionItemProps: ISuggestionItemProps<T>) => JSXElement;\n\n /** Callback for when the user clicks on the suggestion. */\n onClick: (ev: React.MouseEvent<HTMLButtonElement>) => void;\n\n /** Callback for when the item is removed from the array of suggested items. */\n onRemoveItem: (ev: React.MouseEvent<HTMLButtonElement>) => void;\n\n /** Optional className for the root element of the suggestion item. */\n className?: string;\n\n /** Unique id of the suggested item. */\n id?: string;\n\n /** Whether the remove button should be rendered or not. */\n showRemoveButton?: boolean;\n\n /** An override for the 'selected' property of the SuggestionModel. */\n isSelectedOverride?: boolean;\n\n /**\n * The ARIA label for the button to remove the suggestion from the list.\n */\n removeButtonAriaLabel?: string;\n\n /** Call to provide customized styling that will layer on top of the variant rules. */\n styles?: IStyleFunctionOrObject<ISuggestionsItemStyleProps, ISuggestionsItemStyles>;\n\n /** Theme provided by High-Order Component. */\n theme?: ITheme;\n\n /**\n * Props for the icon used in the item's remove button.\n * @defaultvalue `{ iconName:'Cancel' }`\n */\n removeButtonIconProps?: IIconProps;\n}\n\n/**\n * The props needed to construct SuggestionItem styles.\n * {@docCategory Pickers}\n */\nexport type ISuggestionsItemStyleProps = Required<Pick<ISuggestionItemProps<any>, 'theme'>> &\n Pick<ISuggestionItemProps<any>, 'className'> & {\n /** Whether the suggestion item is selected or not. */\n suggested?: boolean;\n };\n\n/**\n * Represents the stylable areas of the SuggestionItem.\n * {@docCategory Pickers}\n */\nexport interface ISuggestionsItemStyles {\n /** Root element of the suggested item. */\n root: IStyle;\n\n /** Refers to the CommandButton holding the content of the suggested item. */\n itemButton: IStyle;\n\n /** Refers to the remove button in case it's rendered. */\n closeButton: IStyle;\n}\n"]}
@@ -0,0 +1,8 @@
import * as React from 'react';
import type { ITagItemProps } from './TagPicker.types';
import type { JSXElement } from '@fluentui/utilities';
/**
* {@docCategory TagPicker}
*/
export declare const TagItemBase: (props: ITagItemProps) => JSXElement;
export declare const TagItem: React.FunctionComponent<React.PropsWithChildren<React.PropsWithChildren<ITagItemProps>>>;
@@ -0,0 +1,45 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TagItem = exports.TagItemBase = void 0;
var tslib_1 = require("tslib");
var React = require("react");
var Utilities_1 = require("../../../Utilities");
var Button_1 = require("../../../Button");
var TagItem_styles_1 = require("./TagItem.styles");
var react_hooks_1 = require("@fluentui/react-hooks");
var getClassNames = (0, Utilities_1.classNamesFunction)();
/**
* {@docCategory TagPicker}
*/
var TagItemBase = function (props) {
var theme = props.theme, styles = props.styles, selected = props.selected, disabled = props.disabled, enableTagFocusInDisabledPicker = props.enableTagFocusInDisabledPicker, children = props.children, className = props.className, index = props.index, onRemoveItem = props.onRemoveItem, removeButtonAriaLabel = props.removeButtonAriaLabel, _a = props.title, title = _a === void 0 ? typeof props.children === 'string' ? props.children : props.item.name : _a, removeButtonIconProps = props.removeButtonIconProps, removeButtonProps = props.removeButtonProps;
var buttonRef = React.createRef();
var handleClick = function () {
var _a;
(_a = buttonRef.current) === null || _a === void 0 ? void 0 : _a.focus();
};
var classNames = getClassNames(styles, {
theme: theme,
className: className,
selected: selected,
disabled: disabled,
});
var itemId = (0, react_hooks_1.useId)();
var disabledAttrs = enableTagFocusInDisabledPicker
? {
'aria-disabled': disabled,
tabindex: 0,
}
: {
disabled: disabled,
};
return (React.createElement("div", { "data-selection-index": index, className: classNames.root, role: 'listitem', key: index, onClick: handleClick },
React.createElement("span", { className: classNames.text, title: title, id: "".concat(itemId, "-text") }, children),
React.createElement(Button_1.IconButton, tslib_1.__assign({ componentRef: buttonRef, id: itemId, onClick: onRemoveItem }, disabledAttrs, { iconProps: removeButtonIconProps !== null && removeButtonIconProps !== void 0 ? removeButtonIconProps : { iconName: 'Cancel' }, styles: { icon: { fontSize: '12px' } }, className: classNames.close, "aria-labelledby": "".concat(itemId, "-removeLabel ").concat(itemId, "-text") }, removeButtonProps)),
React.createElement("span", { id: "".concat(itemId, "-removeLabel"), hidden: true }, removeButtonAriaLabel)));
};
exports.TagItemBase = TagItemBase;
exports.TagItem = (0, Utilities_1.styled)(exports.TagItemBase, TagItem_styles_1.getStyles, undefined, {
scope: 'TagItem',
});
//# sourceMappingURL=TagItem.js.map
@@ -0,0 +1 @@
{"version":3,"file":"TagItem.js","sourceRoot":"../src/","sources":["components/pickers/TagPicker/TagItem.tsx"],"names":[],"mappings":";;;;AAAA,6BAA+B;AAE/B,gDAAgE;AAChE,0CAAsD;AACtD,mDAA6C;AAC7C,qDAA8C;AAK9C,IAAM,aAAa,GAAG,IAAA,8BAAkB,GAAsC,CAAC;AAE/E;;GAEG;AAEI,IAAM,WAAW,GAAG,UAAC,KAAoB;IAE5C,IAAA,KAAK,GAaH,KAAK,MAbF,EACL,MAAM,GAYJ,KAAK,OAZD,EACN,QAAQ,GAWN,KAAK,SAXC,EACR,QAAQ,GAUN,KAAK,SAVC,EACR,8BAA8B,GAS5B,KAAK,+BATuB,EAC9B,QAAQ,GAQN,KAAK,SARC,EACR,SAAS,GAOP,KAAK,UAPE,EACT,KAAK,GAMH,KAAK,MANF,EACL,YAAY,GAKV,KAAK,aALK,EACZ,qBAAqB,GAInB,KAAK,sBAJc,EACrB,KAGE,KAAK,MAHsE,EAA7E,KAAK,mBAAG,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,KAAA,EAC7E,qBAAqB,GAEnB,KAAK,sBAFc,EACrB,iBAAiB,GACf,KAAK,kBADU,CACT;IAEV,IAAM,SAAS,GAAG,KAAK,CAAC,SAAS,EAAW,CAAC;IAE7C,IAAM,WAAW,GAA4C;;QAC3D,MAAA,SAAS,CAAC,OAAO,0CAAE,KAAK,EAAE,CAAC;IAC7B,CAAC,CAAC;IAEF,IAAM,UAAU,GAAG,aAAa,CAAC,MAAM,EAAE;QACvC,KAAK,EAAE,KAAM;QACb,SAAS,WAAA;QACT,QAAQ,UAAA;QACR,QAAQ,UAAA;KACT,CAAC,CAAC;IAEH,IAAM,MAAM,GAAG,IAAA,mBAAK,GAAE,CAAC;IAEvB,IAAM,aAAa,GAAG,8BAA8B;QAClD,CAAC,CAAC;YACE,eAAe,EAAE,QAAQ;YACzB,QAAQ,EAAE,CAAC;SACZ;QACH,CAAC,CAAC;YACE,QAAQ,UAAA;SACT,CAAC;IAEN,OAAO,CACL,qDAA2B,KAAK,EAAE,SAAS,EAAE,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW;QAC9G,8BAAM,SAAS,EAAE,UAAU,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,UAAG,MAAM,UAAO,IACjE,QAAQ,CACJ;QACP,oBAAC,mBAAU,qBACT,YAAY,EAAE,SAAS,EACvB,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,YAAY,IACjB,aAAa,IACjB,SAAS,EAAE,qBAAqB,aAArB,qBAAqB,cAArB,qBAAqB,GAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAC1D,MAAM,EAAE,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EACtC,SAAS,EAAE,UAAU,CAAC,KAAK,qBACV,UAAG,MAAM,0BAAgB,MAAM,UAAO,IACnD,iBAAiB,EACrB;QACF,8BAAM,EAAE,EAAE,UAAG,MAAM,iBAAc,EAAE,MAAM,UACtC,qBAAqB,CACjB,CACH,CACP,CAAC;AACJ,CAAC,CAAC;AA9DW,QAAA,WAAW,eA8DtB;AAEW,QAAA,OAAO,GAAG,IAAA,kBAAM,EAAoD,mBAAW,EAAE,0BAAS,EAAE,SAAS,EAAE;IAClH,KAAK,EAAE,SAAS;CACjB,CAAC,CAAC","sourcesContent":["import * as React from 'react';\n\nimport { styled, classNamesFunction } from '../../../Utilities';\nimport { IconButton, IButton } from '../../../Button';\nimport { getStyles } from './TagItem.styles';\nimport { useId } from '@fluentui/react-hooks';\nimport type { ITagItemProps, ITagItemStyleProps, ITagItemStyles } from './TagPicker.types';\n\nimport type { JSXElement } from '@fluentui/utilities';\n\nconst getClassNames = classNamesFunction<ITagItemStyleProps, ITagItemStyles>();\n\n/**\n * {@docCategory TagPicker}\n */\n\nexport const TagItemBase = (props: ITagItemProps): JSXElement => {\n const {\n theme,\n styles,\n selected,\n disabled,\n enableTagFocusInDisabledPicker,\n children,\n className,\n index,\n onRemoveItem,\n removeButtonAriaLabel,\n title = typeof props.children === 'string' ? props.children : props.item.name,\n removeButtonIconProps,\n removeButtonProps,\n } = props;\n\n const buttonRef = React.createRef<IButton>();\n\n const handleClick: React.MouseEventHandler<HTMLDivElement> = () => {\n buttonRef.current?.focus();\n };\n\n const classNames = getClassNames(styles, {\n theme: theme!,\n className,\n selected,\n disabled,\n });\n\n const itemId = useId();\n\n const disabledAttrs = enableTagFocusInDisabledPicker\n ? {\n 'aria-disabled': disabled,\n tabindex: 0,\n }\n : {\n disabled,\n };\n\n return (\n <div data-selection-index={index} className={classNames.root} role={'listitem'} key={index} onClick={handleClick}>\n <span className={classNames.text} title={title} id={`${itemId}-text`}>\n {children}\n </span>\n <IconButton\n componentRef={buttonRef}\n id={itemId}\n onClick={onRemoveItem}\n {...disabledAttrs}\n iconProps={removeButtonIconProps ?? { iconName: 'Cancel' }}\n styles={{ icon: { fontSize: '12px' } }}\n className={classNames.close}\n aria-labelledby={`${itemId}-removeLabel ${itemId}-text`}\n {...removeButtonProps}\n />\n <span id={`${itemId}-removeLabel`} hidden>\n {removeButtonAriaLabel}\n </span>\n </div>\n );\n};\n\nexport const TagItem = styled<ITagItemProps, ITagItemStyleProps, ITagItemStyles>(TagItemBase, getStyles, undefined, {\n scope: 'TagItem',\n});\n"]}
@@ -0,0 +1,2 @@
import type { ITagItemStyleProps, ITagItemStyles } from './TagPicker.types';
export declare function getStyles(props: ITagItemStyleProps): ITagItemStyles;
@@ -0,0 +1,141 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getStyles = getStyles;
var Styling_1 = require("../../../Styling");
var BaseButton_classNames_1 = require("../../Button/BaseButton.classNames");
var Utilities_1 = require("../../../Utilities");
var GlobalClassNames = {
root: 'ms-TagItem',
text: 'ms-TagItem-text',
close: 'ms-TagItem-close',
isSelected: 'is-selected',
};
var TAG_HEIGHT = 26;
function getStyles(props) {
var _a, _b, _c, _d, _e, _f;
var className = props.className, theme = props.theme, selected = props.selected, disabled = props.disabled;
var palette = theme.palette, effects = theme.effects, fonts = theme.fonts, semanticColors = theme.semanticColors;
var classNames = (0, Styling_1.getGlobalClassNames)(GlobalClassNames, theme);
return {
root: [
classNames.root,
fonts.medium,
(0, Styling_1.getFocusStyle)(theme),
{
boxSizing: 'content-box',
flexShrink: '1',
margin: 2,
height: TAG_HEIGHT,
lineHeight: TAG_HEIGHT,
cursor: 'default',
userSelect: 'none',
display: 'flex',
flexWrap: 'nowrap',
maxWidth: 300,
minWidth: 0, // needed to prevent long tags from overflowing container
borderRadius: effects.roundedCorner2,
color: semanticColors.inputText,
background: palette.neutralLighter,
selectors: (_a = {
':hover': [
!disabled &&
!selected && {
color: palette.neutralDark,
background: palette.neutralLight,
selectors: {
'.ms-TagItem-close': {
color: palette.neutralPrimary,
},
},
},
disabled && { background: palette.neutralLighter },
]
},
_a[Styling_1.HighContrastSelector] = {
border: "1px solid ".concat(!selected ? 'WindowText' : 'WindowFrame'),
},
_a),
},
disabled && {
selectors: (_b = {},
_b[Styling_1.HighContrastSelector] = {
borderColor: 'GrayText',
},
_b),
},
selected &&
!disabled && [
classNames.isSelected,
{
':focus-within': (_c = {
background: palette.themePrimary,
color: palette.white
},
_c[Styling_1.HighContrastSelector] = {
color: 'HighLightText',
background: 'Highlight',
},
_c),
},
],
className,
],
text: [
classNames.text,
{
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
minWidth: 30,
margin: '0 8px',
},
disabled && {
selectors: (_d = {},
_d[Styling_1.HighContrastSelector] = {
color: 'GrayText',
},
_d),
},
],
close: [
classNames.close,
(0, Styling_1.getFocusStyle)(theme, { borderColor: 'transparent', inset: 1, outlineColor: palette.white }),
{
color: palette.neutralSecondary,
width: 30,
height: '100%',
flex: '0 0 auto',
borderRadius: (0, Utilities_1.getRTL)(theme)
? "".concat(effects.roundedCorner2, " 0 0 ").concat(effects.roundedCorner2)
: "0 ".concat(effects.roundedCorner2, " ").concat(effects.roundedCorner2, " 0"),
selectors: (_e = {
':hover': {
background: palette.neutralQuaternaryAlt,
color: palette.neutralPrimary,
}
},
_e[".".concat(classNames.isSelected, " &:focus")] = {
color: palette.white,
background: palette.themePrimary,
},
_e[':focus:hover'] = {
color: palette.white,
background: palette.themeDark,
},
_e[':active'] = {
color: palette.white,
backgroundColor: palette.themeDark,
},
_e),
},
disabled && {
selectors: (_f = {},
_f[".".concat(BaseButton_classNames_1.ButtonGlobalClassNames.msButtonIcon)] = {
color: palette.neutralSecondary,
},
_f),
},
],
};
}
//# sourceMappingURL=TagItem.styles.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,8 @@
import * as React from 'react';
import type { ITagItemSuggestionProps } from './TagPicker.types';
import type { JSXElement } from '@fluentui/utilities';
/**
* {@docCategory TagPicker}
*/
export declare const TagItemSuggestionBase: (props: ITagItemSuggestionProps) => JSXElement;
export declare const TagItemSuggestion: React.FunctionComponent<React.PropsWithChildren<React.PropsWithChildren<ITagItemSuggestionProps>>>;
@@ -0,0 +1,24 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TagItemSuggestion = exports.TagItemSuggestionBase = void 0;
var tslib_1 = require("tslib");
var React = require("react");
var Utilities_1 = require("../../../Utilities");
var TagItemSuggestion_styles_1 = require("./TagItemSuggestion.styles");
var getClassNames = (0, Utilities_1.classNamesFunction)();
/**
* {@docCategory TagPicker}
*/
var TagItemSuggestionBase = function (props) {
var styles = props.styles, theme = props.theme, children = props.children, rest = tslib_1.__rest(props, ["styles", "theme", "children"]);
var classNames = getClassNames(styles, {
theme: theme,
});
return (React.createElement("div", tslib_1.__assign({ className: classNames.suggestionTextOverflow }, rest),
' ',
children,
' '));
};
exports.TagItemSuggestionBase = TagItemSuggestionBase;
exports.TagItemSuggestion = (0, Utilities_1.styled)(exports.TagItemSuggestionBase, TagItemSuggestion_styles_1.getStyles, undefined, { scope: 'TagItemSuggestion' });
//# sourceMappingURL=TagItemSuggestion.js.map
@@ -0,0 +1 @@
{"version":3,"file":"TagItemSuggestion.js","sourceRoot":"../src/","sources":["components/pickers/TagPicker/TagItemSuggestion.tsx"],"names":[],"mappings":";;;;AAAA,6BAA+B;AAE/B,gDAAgE;AAChE,uEAAuD;AASvD,IAAM,aAAa,GAAG,IAAA,8BAAkB,GAA0D,CAAC;AAEnG;;GAEG;AAEI,IAAM,qBAAqB,GAAG,UAAC,KAA8B;IAC1D,IAAA,MAAM,GAA+B,KAAK,OAApC,EAAE,KAAK,GAAwB,KAAK,MAA7B,EAAE,QAAQ,GAAc,KAAK,SAAnB,EAAK,IAAI,kBAAK,KAAK,EAA5C,+BAAoC,CAAF,CAAW;IAEnD,IAAM,UAAU,GAAG,aAAa,CAAC,MAAM,EAAE;QACvC,KAAK,EAAE,KAAM;KACd,CAAC,CAAC;IAEH,OAAO,CACL,8CAAK,SAAS,EAAE,UAAU,CAAC,sBAAsB,IAAM,IAAI;QACxD,GAAG;QACH,QAAQ;QAAE,GAAG,CACV,CACP,CAAC;AACJ,CAAC,CAAC;AAbW,QAAA,qBAAqB,yBAahC;AAEW,QAAA,iBAAiB,GAAG,IAAA,kBAAM,EAIrC,6BAAqB,EAAE,oCAAS,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAC,CAAC","sourcesContent":["import * as React from 'react';\n\nimport { classNamesFunction, styled } from '../../../Utilities';\nimport { getStyles } from './TagItemSuggestion.styles';\nimport type {\n ITagItemSuggestionProps,\n ITagItemSuggestionStyleProps,\n ITagItemSuggestionStyles,\n} from './TagPicker.types';\n\nimport type { JSXElement } from '@fluentui/utilities';\n\nconst getClassNames = classNamesFunction<ITagItemSuggestionStyleProps, ITagItemSuggestionStyles>();\n\n/**\n * {@docCategory TagPicker}\n */\n\nexport const TagItemSuggestionBase = (props: ITagItemSuggestionProps): JSXElement => {\n const { styles, theme, children, ...rest } = props;\n\n const classNames = getClassNames(styles, {\n theme: theme!,\n });\n\n return (\n <div className={classNames.suggestionTextOverflow} {...rest}>\n {' '}\n {children}{' '}\n </div>\n );\n};\n\nexport const TagItemSuggestion = styled<\n ITagItemSuggestionProps,\n ITagItemSuggestionStyleProps,\n ITagItemSuggestionStyles\n>(TagItemSuggestionBase, getStyles, undefined, { scope: 'TagItemSuggestion' });\n"]}
@@ -0,0 +1,2 @@
import type { ITagItemSuggestionStyleProps, ITagItemSuggestionStyles } from './TagPicker.types';
export declare function getStyles(props: ITagItemSuggestionStyleProps): ITagItemSuggestionStyles;
@@ -0,0 +1,25 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getStyles = getStyles;
var Styling_1 = require("../../../Styling");
var GlobalClassNames = {
suggestionTextOverflow: 'ms-TagItem-TextOverflow',
};
function getStyles(props) {
var className = props.className, theme = props.theme;
var classNames = (0, Styling_1.getGlobalClassNames)(GlobalClassNames, theme);
return {
suggestionTextOverflow: [
classNames.suggestionTextOverflow,
{
overflow: 'hidden',
textOverflow: 'ellipsis',
maxWidth: '60vw',
padding: '6px 12px 7px',
whiteSpace: 'nowrap',
},
className,
],
};
}
//# sourceMappingURL=TagItemSuggestion.styles.js.map
@@ -0,0 +1 @@
{"version":3,"file":"TagItemSuggestion.styles.js","sourceRoot":"../src/","sources":["components/pickers/TagPicker/TagItemSuggestion.styles.ts"],"names":[],"mappings":";;AAOA,8BAkBC;AAzBD,4CAAuD;AAGvD,IAAM,gBAAgB,GAAG;IACvB,sBAAsB,EAAE,yBAAyB;CAClD,CAAC;AAEF,SAAgB,SAAS,CAAC,KAAmC;IACnD,IAAA,SAAS,GAAY,KAAK,UAAjB,EAAE,KAAK,GAAK,KAAK,MAAV,CAAW;IAEnC,IAAM,UAAU,GAAG,IAAA,6BAAmB,EAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;IAEhE,OAAO;QACL,sBAAsB,EAAE;YACtB,UAAU,CAAC,sBAAsB;YACjC;gBACE,QAAQ,EAAE,QAAQ;gBAClB,YAAY,EAAE,UAAU;gBACxB,QAAQ,EAAE,MAAM;gBAChB,OAAO,EAAE,cAAc;gBACvB,UAAU,EAAE,QAAQ;aACrB;YACD,SAAS;SACV;KACF,CAAC;AACJ,CAAC","sourcesContent":["import { getGlobalClassNames } from '../../../Styling';\nimport type { ITagItemSuggestionStyleProps, ITagItemSuggestionStyles } from './TagPicker.types';\n\nconst GlobalClassNames = {\n suggestionTextOverflow: 'ms-TagItem-TextOverflow',\n};\n\nexport function getStyles(props: ITagItemSuggestionStyleProps): ITagItemSuggestionStyles {\n const { className, theme } = props;\n\n const classNames = getGlobalClassNames(GlobalClassNames, theme);\n\n return {\n suggestionTextOverflow: [\n classNames.suggestionTextOverflow,\n {\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n maxWidth: '60vw',\n padding: '6px 12px 7px',\n whiteSpace: 'nowrap',\n },\n className,\n ],\n };\n}\n"]}
@@ -0,0 +1,14 @@
import * as React from 'react';
import { BasePicker } from '../BasePicker';
import type { ITagPickerProps, ITag, ITagItemProps } from './TagPicker.types';
import type { JSXElement } from '@fluentui/utilities';
/**
* {@docCategory TagPicker}
*/
export declare class TagPickerBase extends BasePicker<ITag, ITagPickerProps> {
static defaultProps: {
onRenderItem: (props: ITagItemProps) => JSXElement;
onRenderSuggestionsItem: (props: ITag) => JSXElement;
};
}
export declare const TagPicker: React.FunctionComponent<React.PropsWithChildren<React.PropsWithChildren<ITagPickerProps>>>;
@@ -0,0 +1,29 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TagPicker = exports.TagPickerBase = void 0;
var tslib_1 = require("tslib");
var React = require("react");
var Utilities_1 = require("../../../Utilities");
var BasePicker_1 = require("../BasePicker");
var BasePicker_styles_1 = require("../BasePicker.styles");
var TagItem_1 = require("./TagItem");
var TagItemSuggestion_1 = require("./TagItemSuggestion");
/**
* {@docCategory TagPicker}
*/
var TagPickerBase = /** @class */ (function (_super) {
tslib_1.__extends(TagPickerBase, _super);
function TagPickerBase() {
return _super !== null && _super.apply(this, arguments) || this;
}
TagPickerBase.defaultProps = {
onRenderItem: function (props) { return React.createElement(TagItem_1.TagItem, tslib_1.__assign({}, props), props.item.name); },
onRenderSuggestionsItem: function (props) { return React.createElement(TagItemSuggestion_1.TagItemSuggestion, null, props.name); },
};
return TagPickerBase;
}(BasePicker_1.BasePicker));
exports.TagPickerBase = TagPickerBase;
exports.TagPicker = (0, Utilities_1.styled)(TagPickerBase, BasePicker_styles_1.getStyles, undefined, {
scope: 'TagPicker',
});
//# sourceMappingURL=TagPicker.js.map
@@ -0,0 +1 @@
{"version":3,"file":"TagPicker.js","sourceRoot":"../src/","sources":["components/pickers/TagPicker/TagPicker.tsx"],"names":[],"mappings":";;;;AAAA,6BAA+B;AAC/B,gDAA4C;AAC5C,4CAA2C;AAC3C,0DAAiD;AACjD,qCAAoC;AACpC,yDAAwD;AAMxD;;GAEG;AACH;IAAmC,yCAAiC;IAApE;;IAMA,CAAC;IALe,0BAAY,GAAG;QAC3B,YAAY,EAAE,UAAC,KAAoB,IAAiB,OAAA,oBAAC,iBAAO,uBAAK,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAW,EAA/C,CAA+C;QAEnG,uBAAuB,EAAE,UAAC,KAAW,IAAiB,OAAA,oBAAC,qCAAiB,QAAE,KAAK,CAAC,IAAI,CAAqB,EAAnD,CAAmD;KAC1G,CAAC;IACJ,oBAAC;CAAA,AAND,CAAmC,uBAAU,GAM5C;AANY,sCAAa;AAQb,QAAA,SAAS,GAAG,IAAA,kBAAM,EAC7B,aAAa,EACb,6BAAS,EACT,SAAS,EACT;IACE,KAAK,EAAE,WAAW;CACnB,CACF,CAAC","sourcesContent":["import * as React from 'react';\nimport { styled } from '../../../Utilities';\nimport { BasePicker } from '../BasePicker';\nimport { getStyles } from '../BasePicker.styles';\nimport { TagItem } from './TagItem';\nimport { TagItemSuggestion } from './TagItemSuggestion';\nimport type { IBasePickerStyleProps, IBasePickerStyles } from '../BasePicker.types';\nimport type { ITagPickerProps, ITag, ITagItemProps } from './TagPicker.types';\n\nimport type { JSXElement } from '@fluentui/utilities';\n\n/**\n * {@docCategory TagPicker}\n */\nexport class TagPickerBase extends BasePicker<ITag, ITagPickerProps> {\n public static defaultProps = {\n onRenderItem: (props: ITagItemProps): JSXElement => <TagItem {...props}>{props.item.name}</TagItem>,\n\n onRenderSuggestionsItem: (props: ITag): JSXElement => <TagItemSuggestion>{props.name}</TagItemSuggestion>,\n };\n}\n\nexport const TagPicker = styled<ITagPickerProps, IBasePickerStyleProps, IBasePickerStyles>(\n TagPickerBase,\n getStyles,\n undefined,\n {\n scope: 'TagPicker',\n },\n);\n"]}
@@ -0,0 +1,96 @@
import * as React from 'react';
import type { IStyle, ITheme } from '../../../Styling';
import type { IStyleFunctionOrObject } from '../../../Utilities';
import type { IPickerItemProps } from '../PickerItem.types';
import type { IBasePickerProps } from '../BasePicker.types';
import type { IButtonProps } from '../../Button/Button.types';
/**
* TagPickerItem item interface.
* {@docCategory TagPicker}
*/
export interface ITag {
/** Name of the item. */
name: string;
/** Unique key for the item. */
key: string | number;
}
/**
* TagPicker component props
* {@docCategory TagPicker}
*/
export interface ITagPickerProps extends IBasePickerProps<ITag> {
}
/**
* TagItem remove button component props
* {@docCategory TagPicker}
*/
export interface ITagItemRemoveButtonProps extends IButtonProps {
/** data-id to manually trigger interaction or to identify users' interactions */
'data-id'?: string;
}
/**
* TagItem component props
* {@docCategory TagPicker}
*/
export interface ITagItemProps extends IPickerItemProps<ITag> {
/** Additional CSS class(es) to apply to the TagItem root element. */
className?: string;
/**
* Enable or not focus on TagItem when TagPicker is disabled.
* @defaultvalue false
*/
enableTagFocusInDisabledPicker?: boolean;
/**
* The title (and aria-label) attribute used by the TagItem text element.
* @defaultvalue children if of type string or item.name
*/
title?: string;
/** Call to provide customized styling that will layer on top of the variant rules. */
styles?: IStyleFunctionOrObject<ITagItemStyleProps, ITagItemStyles>;
/** Theme provided by High-Order Component. */
theme?: ITheme;
/** Allows to pass any additional props directly to the remove IconButton. */
removeButtonProps?: ITagItemRemoveButtonProps;
}
/**
* The props needed to construct TagItem styles.
* {@docCategory TagPicker}
*/
export type ITagItemStyleProps = Required<Pick<ITagItemProps, 'theme'>> & Pick<ITagItemProps, 'className' | 'selected' | 'disabled'> & {};
/**
* Represents the stylable areas of the TagItem.
* {@docCategory TagPicker}
*/
export interface ITagItemStyles {
/** Root element of picked TagItem */
root: IStyle;
/** Refers to the text element of the TagItem already picked. */
text: IStyle;
/** Refers to the cancel action button on a picked TagItem. */
close: IStyle;
}
/**
* TagItemSuggestion component props
* {@docCategory TagPicker}
*/
export interface ITagItemSuggestionProps extends React.AllHTMLAttributes<HTMLElement> {
/** Additional CSS class(es) to apply to the TagItemSuggestion div element */
className?: string;
/** Call to provide customized styling that will layer on top of the variant rules. */
styles?: IStyleFunctionOrObject<ITagItemSuggestionStyleProps, ITagItemSuggestionStyles>;
/** Theme provided by High-Order Component. */
theme?: ITheme;
}
/**
* The props needed to construct TagItemSuggestion styles.
* {@docCategory TagPicker}
*/
export type ITagItemSuggestionStyleProps = Required<Pick<ITagItemSuggestionProps, 'theme'>> & Pick<ITagItemSuggestionProps, 'className'> & {};
/**
* Represents the stylable areas of the TagItemSuggestion
* {@docCategory TagPicker}
*/
export interface ITagItemSuggestionStyles {
/** Refers to the text element of the TagItemSuggestion */
suggestionTextOverflow?: IStyle;
}
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=TagPicker.types.js.map
@@ -0,0 +1 @@
{"version":3,"file":"TagPicker.types.js","sourceRoot":"../src/","sources":["components/pickers/TagPicker/TagPicker.types.ts"],"names":[],"mappings":"","sourcesContent":["import * as React from 'react';\nimport type { IStyle, ITheme } from '../../../Styling';\nimport type { IStyleFunctionOrObject } from '../../../Utilities';\nimport type { IPickerItemProps } from '../PickerItem.types';\nimport type { IBasePickerProps } from '../BasePicker.types';\nimport type { IButtonProps } from '../../Button/Button.types';\n\n/**\n * TagPickerItem item interface.\n * {@docCategory TagPicker}\n */\nexport interface ITag {\n /** Name of the item. */\n name: string;\n\n /** Unique key for the item. */\n key: string | number;\n}\n\n/**\n * TagPicker component props\n * {@docCategory TagPicker}\n */\nexport interface ITagPickerProps extends IBasePickerProps<ITag> {}\n\n/**\n * TagItem remove button component props\n * {@docCategory TagPicker}\n */\nexport interface ITagItemRemoveButtonProps extends IButtonProps {\n /** data-id to manually trigger interaction or to identify users' interactions */\n 'data-id'?: string;\n}\n\n/**\n * TagItem component props\n * {@docCategory TagPicker}\n */\nexport interface ITagItemProps extends IPickerItemProps<ITag> {\n /** Additional CSS class(es) to apply to the TagItem root element. */\n className?: string;\n\n /**\n * Enable or not focus on TagItem when TagPicker is disabled.\n * @defaultvalue false\n */\n enableTagFocusInDisabledPicker?: boolean;\n\n /**\n * The title (and aria-label) attribute used by the TagItem text element.\n * @defaultvalue children if of type string or item.name\n */\n title?: string;\n\n /** Call to provide customized styling that will layer on top of the variant rules. */\n styles?: IStyleFunctionOrObject<ITagItemStyleProps, ITagItemStyles>;\n\n /** Theme provided by High-Order Component. */\n theme?: ITheme;\n\n /** Allows to pass any additional props directly to the remove IconButton. */\n removeButtonProps?: ITagItemRemoveButtonProps;\n}\n\n/**\n * The props needed to construct TagItem styles.\n * {@docCategory TagPicker}\n */\nexport type ITagItemStyleProps = Required<Pick<ITagItemProps, 'theme'>> &\n Pick<ITagItemProps, 'className' | 'selected' | 'disabled'> & {};\n\n/**\n * Represents the stylable areas of the TagItem.\n * {@docCategory TagPicker}\n */\nexport interface ITagItemStyles {\n /** Root element of picked TagItem */\n root: IStyle;\n\n /** Refers to the text element of the TagItem already picked. */\n text: IStyle;\n\n /** Refers to the cancel action button on a picked TagItem. */\n close: IStyle;\n}\n\n/**\n * TagItemSuggestion component props\n * {@docCategory TagPicker}\n */\nexport interface ITagItemSuggestionProps extends React.AllHTMLAttributes<HTMLElement> {\n /** Additional CSS class(es) to apply to the TagItemSuggestion div element */\n className?: string;\n\n /** Call to provide customized styling that will layer on top of the variant rules. */\n styles?: IStyleFunctionOrObject<ITagItemSuggestionStyleProps, ITagItemSuggestionStyles>;\n\n /** Theme provided by High-Order Component. */\n theme?: ITheme;\n}\n\n/**\n * The props needed to construct TagItemSuggestion styles.\n * {@docCategory TagPicker}\n */\nexport type ITagItemSuggestionStyleProps = Required<Pick<ITagItemSuggestionProps, 'theme'>> &\n Pick<ITagItemSuggestionProps, 'className'> & {};\n\n/**\n * Represents the stylable areas of the TagItemSuggestion\n * {@docCategory TagPicker}\n */\nexport interface ITagItemSuggestionStyles {\n /** Refers to the text element of the TagItemSuggestion */\n suggestionTextOverflow?: IStyle;\n}\n"]}
@@ -0,0 +1,25 @@
export * from './Suggestions/Suggestions';
export { getStyles as getSuggestionsStyles } from './Suggestions/Suggestions.styles';
export * from './Suggestions/Suggestions.types';
export * from './Suggestions/SuggestionsItem';
export { getStyles as getSuggestionsItemStyles } from './Suggestions/SuggestionsItem.styles';
export * from './Suggestions/SuggestionsItem.types';
export * from './Suggestions/SuggestionsController';
export * from './AutoFill/BaseAutoFill';
export * from './AutoFill/BaseAutoFill.types';
export * from './BasePicker';
export { getStyles as getBasePickerStyles } from './BasePicker.styles';
export * from './BasePicker.types';
export * from './PickerItem.types';
export * from './PeoplePicker/PeoplePicker';
export { getStyles as getPeoplePickerItemStyles } from './PeoplePicker/PeoplePickerItems/PeoplePickerItem.styles';
export * from './PeoplePicker/PeoplePickerItems/PeoplePickerItem.types';
export * from './PeoplePicker/PeoplePickerItems/PeoplePickerItem';
export * from './PeoplePicker/PeoplePickerItems/PeoplePickerItemSuggestion';
export { getStyles as getPeoplePickerItemSuggestionStyles } from './PeoplePicker/PeoplePickerItems/PeoplePickerItemSuggestion.styles';
export * from './TagPicker/TagPicker';
export * from './TagPicker/TagPicker.types';
export * from './TagPicker/TagItem';
export { getStyles as getTagItemStyles } from './TagPicker/TagItem.styles';
export * from './TagPicker/TagItemSuggestion';
export { getStyles as getTagItemSuggestionStyles } from './TagPicker/TagItemSuggestion.styles';
+37
View File
@@ -0,0 +1,37 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getTagItemSuggestionStyles = exports.getTagItemStyles = exports.getPeoplePickerItemSuggestionStyles = exports.getPeoplePickerItemStyles = exports.getBasePickerStyles = exports.getSuggestionsItemStyles = exports.getSuggestionsStyles = void 0;
var tslib_1 = require("tslib");
tslib_1.__exportStar(require("./Suggestions/Suggestions"), exports);
var Suggestions_styles_1 = require("./Suggestions/Suggestions.styles");
Object.defineProperty(exports, "getSuggestionsStyles", { enumerable: true, get: function () { return Suggestions_styles_1.getStyles; } });
tslib_1.__exportStar(require("./Suggestions/Suggestions.types"), exports);
tslib_1.__exportStar(require("./Suggestions/SuggestionsItem"), exports);
var SuggestionsItem_styles_1 = require("./Suggestions/SuggestionsItem.styles");
Object.defineProperty(exports, "getSuggestionsItemStyles", { enumerable: true, get: function () { return SuggestionsItem_styles_1.getStyles; } });
tslib_1.__exportStar(require("./Suggestions/SuggestionsItem.types"), exports);
tslib_1.__exportStar(require("./Suggestions/SuggestionsController"), exports);
tslib_1.__exportStar(require("./AutoFill/BaseAutoFill"), exports);
tslib_1.__exportStar(require("./AutoFill/BaseAutoFill.types"), exports);
tslib_1.__exportStar(require("./BasePicker"), exports);
var BasePicker_styles_1 = require("./BasePicker.styles");
Object.defineProperty(exports, "getBasePickerStyles", { enumerable: true, get: function () { return BasePicker_styles_1.getStyles; } });
tslib_1.__exportStar(require("./BasePicker.types"), exports);
tslib_1.__exportStar(require("./PickerItem.types"), exports);
tslib_1.__exportStar(require("./PeoplePicker/PeoplePicker"), exports);
var PeoplePickerItem_styles_1 = require("./PeoplePicker/PeoplePickerItems/PeoplePickerItem.styles");
Object.defineProperty(exports, "getPeoplePickerItemStyles", { enumerable: true, get: function () { return PeoplePickerItem_styles_1.getStyles; } });
tslib_1.__exportStar(require("./PeoplePicker/PeoplePickerItems/PeoplePickerItem.types"), exports);
tslib_1.__exportStar(require("./PeoplePicker/PeoplePickerItems/PeoplePickerItem"), exports);
tslib_1.__exportStar(require("./PeoplePicker/PeoplePickerItems/PeoplePickerItemSuggestion"), exports);
var PeoplePickerItemSuggestion_styles_1 = require("./PeoplePicker/PeoplePickerItems/PeoplePickerItemSuggestion.styles");
Object.defineProperty(exports, "getPeoplePickerItemSuggestionStyles", { enumerable: true, get: function () { return PeoplePickerItemSuggestion_styles_1.getStyles; } });
tslib_1.__exportStar(require("./TagPicker/TagPicker"), exports);
tslib_1.__exportStar(require("./TagPicker/TagPicker.types"), exports);
tslib_1.__exportStar(require("./TagPicker/TagItem"), exports);
var TagItem_styles_1 = require("./TagPicker/TagItem.styles");
Object.defineProperty(exports, "getTagItemStyles", { enumerable: true, get: function () { return TagItem_styles_1.getStyles; } });
tslib_1.__exportStar(require("./TagPicker/TagItemSuggestion"), exports);
var TagItemSuggestion_styles_1 = require("./TagPicker/TagItemSuggestion.styles");
Object.defineProperty(exports, "getTagItemSuggestionStyles", { enumerable: true, get: function () { return TagItemSuggestion_styles_1.getStyles; } });
//# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"../src/","sources":["components/pickers/index.ts"],"names":[],"mappings":";;;;AAAA,oEAA0C;AAC1C,uEAAqF;AAA5E,0HAAA,SAAS,OAAwB;AAC1C,0EAAgD;AAChD,wEAA8C;AAC9C,+EAA6F;AAApF,kIAAA,SAAS,OAA4B;AAC9C,8EAAoD;AACpD,8EAAoD;AACpD,kEAAwC;AACxC,wEAA8C;AAC9C,uDAA6B;AAC7B,yDAAuE;AAA9D,wHAAA,SAAS,OAAuB;AACzC,6DAAmC;AACnC,6DAAmC;AACnC,sEAA4C;AAC5C,oGAAkH;AAAzG,oIAAA,SAAS,OAA6B;AAC/C,kGAAwE;AACxE,4FAAkE;AAClE,sGAA4E;AAC5E,wHAAsI;AAA7H,wJAAA,SAAS,OAAuC;AACzD,gEAAsC;AACtC,sEAA4C;AAC5C,8DAAoC;AACpC,6DAA2E;AAAlE,kHAAA,SAAS,OAAoB;AACtC,wEAA8C;AAC9C,iFAA+F;AAAtF,sIAAA,SAAS,OAA8B","sourcesContent":["export * from './Suggestions/Suggestions';\nexport { getStyles as getSuggestionsStyles } from './Suggestions/Suggestions.styles';\nexport * from './Suggestions/Suggestions.types';\nexport * from './Suggestions/SuggestionsItem';\nexport { getStyles as getSuggestionsItemStyles } from './Suggestions/SuggestionsItem.styles';\nexport * from './Suggestions/SuggestionsItem.types';\nexport * from './Suggestions/SuggestionsController';\nexport * from './AutoFill/BaseAutoFill';\nexport * from './AutoFill/BaseAutoFill.types';\nexport * from './BasePicker';\nexport { getStyles as getBasePickerStyles } from './BasePicker.styles';\nexport * from './BasePicker.types';\nexport * from './PickerItem.types';\nexport * from './PeoplePicker/PeoplePicker';\nexport { getStyles as getPeoplePickerItemStyles } from './PeoplePicker/PeoplePickerItems/PeoplePickerItem.styles';\nexport * from './PeoplePicker/PeoplePickerItems/PeoplePickerItem.types';\nexport * from './PeoplePicker/PeoplePickerItems/PeoplePickerItem';\nexport * from './PeoplePicker/PeoplePickerItems/PeoplePickerItemSuggestion';\nexport { getStyles as getPeoplePickerItemSuggestionStyles } from './PeoplePicker/PeoplePickerItems/PeoplePickerItemSuggestion.styles';\nexport * from './TagPicker/TagPicker';\nexport * from './TagPicker/TagPicker.types';\nexport * from './TagPicker/TagItem';\nexport { getStyles as getTagItemStyles } from './TagPicker/TagItem.styles';\nexport * from './TagPicker/TagItemSuggestion';\nexport { getStyles as getTagItemSuggestionStyles } from './TagPicker/TagItemSuggestion.styles';\n"]}