@@ -10,8 +10,8 @@ import { customElement, html, internalProperty, property, TemplateResult } from
1010import { classMap } from 'lit-html/directives/class-map' ;
1111import { repeat } from 'lit-html/directives/repeat' ;
1212import { findGroups , GroupType } from '../../graph/graph.groups' ;
13- import { findPeople , getPeopleFromGroup , PersonType } from '../../graph/graph.people' ;
14- import { findUsers , getUser } from '../../graph/graph.user' ;
13+ import { findPeople , getPeople , getPeopleFromGroup , PersonType } from '../../graph/graph.people' ;
14+ import { findUsers , getUser , getUsersForUserIds } from '../../graph/graph.user' ;
1515import { IDynamicPerson } from '../../graph/types' ;
1616import { Providers } from '../../Providers' ;
1717import { ProviderState } from '../../providers/IProvider' ;
@@ -87,36 +87,6 @@ export class MgtPeoplePicker extends MgtTemplatedComponent {
8787 return this . renderRoot . querySelector ( '.flyout' ) ;
8888 }
8989
90- /**
91- * containing object of IDynamicPerson.
92- * @type {IDynamicPerson[] }
93- */
94- @property ( {
95- attribute : 'people' ,
96- type : Object
97- } )
98- public people : IDynamicPerson [ ] ;
99-
100- /**
101- * determining how many people to show in list.
102- * @type {number }
103- */
104- @property ( {
105- attribute : 'show-max' ,
106- type : Number
107- } )
108- public showMax : number ;
109-
110- /**
111- * array of user picked people.
112- * @type {IDynamicPerson[] }
113- */
114- @property ( {
115- attribute : 'selected-people' ,
116- type : Array
117- } )
118- public selectedPeople : IDynamicPerson [ ] ;
119-
12090 /**
12191 * value determining if search is filtered to a group.
12292 * @type {string }
@@ -206,6 +176,51 @@ export class MgtPeoplePicker extends MgtTemplatedComponent {
206176 this . requestStateUpdate ( true ) ;
207177 }
208178
179+ /**
180+ * containing object of IDynamicPerson.
181+ * @type {IDynamicPerson[] }
182+ */
183+ @property ( {
184+ attribute : 'people' ,
185+ type : Object
186+ } )
187+ public people : IDynamicPerson [ ] ;
188+
189+ /**
190+ * determining how many people to show in list.
191+ * @type {number }
192+ */
193+ @property ( {
194+ attribute : 'show-max' ,
195+ type : Number
196+ } )
197+ public showMax : number ;
198+
199+ /**
200+ * array of user picked people.
201+ * @type {IDynamicPerson[] }
202+ */
203+ @property ( {
204+ attribute : 'selected-people' ,
205+ type : Array
206+ } )
207+ public selectedPeople : IDynamicPerson [ ] ;
208+
209+ /**
210+ * array of people to be selected upon intialization
211+ *
212+ * @type {Array }
213+ * @memberof MgtPeoplePicker
214+ */
215+ @property ( {
216+ attribute : 'default-selected-user-ids' ,
217+ converter : value => {
218+ return value . split ( ',' ) . map ( v => v . trim ( ) ) ;
219+ } ,
220+ type : String
221+ } )
222+ public defaultSelectedUserIds : '' ;
223+
209224 /**
210225 * Placeholder text.
211226 *
@@ -246,6 +261,8 @@ export class MgtPeoplePicker extends MgtTemplatedComponent {
246261 private _type : PersonType = PersonType . Person ;
247262 private _groupType : GroupType = GroupType . Any ;
248263
264+ private defaultPeople : IDynamicPerson [ ] ;
265+
249266 // tracking of user arrow key input for selection
250267 private _arrowSelectionCount : number = 0 ;
251268 // List of people requested if group property is provided
@@ -291,14 +308,19 @@ export class MgtPeoplePicker extends MgtTemplatedComponent {
291308 peopleInput . focus ( options ) ;
292309 peopleInput . select ( ) ;
293310
294- window . requestAnimationFrame ( ( ) => {
295- // Mouse is focused on input
296- if ( ! peopleInput . value ) {
297- this . hideFlyout ( ) ;
298- } else {
311+ // handles hiding control if default people have no more selections available
312+ const peopleLeft = this . filterPeople ( this . defaultPeople ) ;
313+ let shouldShow = true ;
314+ if ( peopleLeft && peopleLeft . length === 0 ) {
315+ shouldShow = false ;
316+ }
317+
318+ if ( shouldShow ) {
319+ window . requestAnimationFrame ( ( ) => {
320+ // Mouse is focused on input
299321 this . showFlyout ( ) ;
300- }
301- } ) ;
322+ } ) ;
323+ }
302324 }
303325
304326 /**
@@ -479,6 +501,11 @@ export class MgtPeoplePicker extends MgtTemplatedComponent {
479501 return this . renderNoData ( ) ;
480502 }
481503
504+ // clears focus
505+ for ( const person of people ) {
506+ ( person as IFocusable ) . isFocused = false ;
507+ }
508+
482509 people = people . slice ( 0 , this . showMax ) ;
483510 ( people [ 0 ] as IFocusable ) . isFocused = true ;
484511
@@ -497,8 +524,9 @@ export class MgtPeoplePicker extends MgtTemplatedComponent {
497524 this . renderTemplate ( 'loading' , null ) ||
498525 html `
499526 < div class ="message-parent ">
500- < div label ="search-error-text " aria-label ="loading " class ="loading-text ">
501- ......
527+ < div class ="spinner "> </ div >
528+ < div label ="loading-text " aria-label ="loading " class ="loading-text ">
529+ Loading...
502530 </ div >
503531 </ div >
504532 `
@@ -617,10 +645,30 @@ export class MgtPeoplePicker extends MgtTemplatedComponent {
617645
618646 const provider = Providers . globalProvider ;
619647 if ( ! people && provider && provider . state === ProviderState . SignedIn ) {
620- if ( this . groupId ) {
648+ const graph = provider . graph . forComponent ( this ) ;
649+
650+ // default common people
651+ if ( ! input . length && this . _isFocused ) {
652+ if ( this . defaultPeople ) {
653+ people = this . defaultPeople ;
654+ } else {
655+ people = await getPeople ( graph ) ;
656+ this . defaultPeople = people ;
657+ }
658+ this . _showLoading = false ;
659+ }
660+
661+ if ( this . defaultSelectedUserIds && ! this . selectedPeople . length ) {
662+ const defaultSelectedUsers = await getUsersForUserIds ( graph , this . defaultSelectedUserIds ) ;
663+
664+ this . selectedPeople = [ ...defaultSelectedUsers ] ;
665+ this . requestUpdate ( ) ;
666+ this . fireCustomEvent ( 'selectionChanged' , this . selectedPeople ) ;
667+ }
668+
669+ if ( this . groupId && input ) {
621670 if ( this . _groupPeople === null ) {
622671 try {
623- const graph = provider . graph . forComponent ( this ) ;
624672 this . _groupPeople = await getPeopleFromGroup ( graph , this . groupId ) ;
625673 } catch ( _ ) {
626674 this . _groupPeople = [ ] ;
@@ -629,9 +677,7 @@ export class MgtPeoplePicker extends MgtTemplatedComponent {
629677
630678 people = this . _groupPeople || [ ] ;
631679 } else if ( input ) {
632- const graph = provider . graph . forComponent ( this ) ;
633680 people = [ ] ;
634-
635681 if ( this . type === PersonType . Person || this . type === PersonType . Any ) {
636682 try {
637683 people = ( await findPeople ( graph , input , this . showMax ) ) || [ ] ;
@@ -716,6 +762,7 @@ export class MgtPeoplePicker extends MgtTemplatedComponent {
716762 return p . id !== person . id ;
717763 } ) ;
718764 this . selectedPeople = filteredPersonArr ;
765+ this . loadState ( ) ;
719766 this . fireCustomEvent ( 'selectionChanged' , this . selectedPeople ) ;
720767 }
721768
@@ -738,6 +785,7 @@ export class MgtPeoplePicker extends MgtTemplatedComponent {
738785 this . selectedPeople = [ ...this . selectedPeople , person ] ;
739786 this . fireCustomEvent ( 'selectionChanged' , this . selectedPeople ) ;
740787
788+ this . loadState ( ) ;
741789 this . _foundPeople = [ ] ;
742790 }
743791 }
@@ -749,6 +797,8 @@ export class MgtPeoplePicker extends MgtTemplatedComponent {
749797 if ( input ) {
750798 input . focus ( ) ;
751799 }
800+ this . _showLoading = true ;
801+ this . loadState ( ) ;
752802 }
753803
754804 private lostFocus ( ) {
@@ -815,6 +865,9 @@ export class MgtPeoplePicker extends MgtTemplatedComponent {
815865 this . userInput = '' ;
816866 // remove last person in selected list
817867 this . selectedPeople = this . selectedPeople . splice ( 0 , this . selectedPeople . length - 1 ) ;
868+ // reset flyout position
869+ this . hideFlyout ( ) ;
870+ this . showFlyout ( ) ;
818871 // fire selected people changed event
819872 this . fireCustomEvent ( 'selectionChanged' , this . selectedPeople ) ;
820873 return ;
@@ -837,24 +890,23 @@ export class MgtPeoplePicker extends MgtTemplatedComponent {
837890 * @param input - input text
838891 */
839892 private handleUserSearch ( input : HTMLInputElement ) {
893+ this . _showLoading = true ;
840894 if ( ! this . _debouncedSearch ) {
841895 this . _debouncedSearch = debounce ( async ( ) => {
842- if ( ! this . userInput . length ) {
843- this . _foundPeople = [ ] ;
844- this . hideFlyout ( ) ;
845- this . _showLoading = true ;
846- } else {
847- // Wait a few milliseconds before showing the flyout.
848- // This helps prevent loading state flickering while the user is actively changing the query.
849- const loadingTimeout = setTimeout ( ( ) => {
850- this . _showLoading = true ;
851- } , 400 ) ;
852-
853- await this . loadState ( ) ;
854- clearTimeout ( loadingTimeout ) ;
855- this . _showLoading = false ;
856- this . showFlyout ( ) ;
857- }
896+ // Wait a few milliseconds before showing the flyout.
897+ // This helps prevent loading state flickering while the user is actively changing the query.
898+
899+ const loadingTimeout = setTimeout ( ( ) => {
900+ if ( ! this . userInput . length ) {
901+ this . _foundPeople = [ ] ;
902+ this . hideFlyout ( ) ;
903+ }
904+ } , 400 ) ;
905+
906+ await this . loadState ( ) ;
907+ clearTimeout ( loadingTimeout ) ;
908+ this . _showLoading = false ;
909+ this . showFlyout ( ) ;
858910
859911 this . _arrowSelectionCount = 0 ;
860912 } , 400 ) ;
0 commit comments