1- import { css , customElement , html , LitElement , property } from 'lit-element' ;
2- import { PersonCardInteraction } from '../../PersonCardInteraction ' ;
3-
1+ import { css , customElement , html , LitElement , property , PropertyValues } from 'lit-element' ;
2+ import { classMap } from 'lit-html/directives/class-map ' ;
3+ import { styles } from './mgt-flyout-css' ;
44/**
55 *
66 *
@@ -15,42 +15,23 @@ export class MgtFlyout extends LitElement {
1515 * using the `css` tag function.
1616 */
1717 static get styles ( ) {
18- return css `
19- .title {
20- color: red;
21- }
22- ` ;
18+ return styles ;
2319 }
2420
25- // TODO: create new type
26- @property ( {
27- attribute : 'person-card' ,
28- converter : ( value , type ) => {
29- value = value . toLowerCase ( ) ;
30- if ( typeof PersonCardInteraction [ value ] === 'undefined' ) {
31- return PersonCardInteraction . none ;
32- } else {
33- return PersonCardInteraction [ value ] ;
34- }
35- }
36- } )
37- public personCardInteraction : PersonCardInteraction = PersonCardInteraction . hover ;
38-
3921 /**
4022 *
4123 *
4224 * @type {string }
4325 * @memberof MgtComponent
4426 */
4527 @property ( {
46- attribute : 'my-title ' ,
47- type : String
28+ attribute : 'isOpen ' ,
29+ type : Boolean
4830 } )
49- public myTitle : string = 'My First Component' ;
50- private _mouseLeaveTimeout ;
51- private _mouseEnterTimeout ;
52- private _openLeft : boolean = false ;
53- private _openUp : boolean = false ;
31+ public isOpen : boolean = false ;
32+
33+ private renderedOnce = false ;
34+
5435 @property ( { attribute : false } ) private _isPersonCardVisible : boolean = false ;
5536 @property ( { attribute : false } ) private _personCardShouldRender : boolean = false ;
5637
@@ -84,47 +65,84 @@ export class MgtFlyout extends LitElement {
8465 */
8566 public firstUpdated ( ) { }
8667
68+ /**
69+ * Invoked whenever the element is updated. Implement to perform
70+ * post-updating tasks via DOM APIs, for example, focusing an element.
71+ *
72+ * Setting properties inside this method will trigger the element to update
73+ * again after this update cycle completes.
74+ *
75+ * * @param changedProperties Map of changed properties with old values
76+ */
77+ protected updated ( changedProps : PropertyValues ) {
78+ super . updated ( changedProps ) ;
79+
80+ const anchor = this . renderRoot . querySelector ( '.anchor' ) ;
81+ const flyout = this . renderRoot . querySelector ( '.flyout' ) as HTMLElement ;
82+ if ( flyout && anchor ) {
83+ const flyoutRect = flyout . getBoundingClientRect ( ) ;
84+ const anchorRect = anchor . getBoundingClientRect ( ) ;
85+
86+ const windowWidth = window . innerWidth || document . documentElement . clientWidth ;
87+ const windowHeight = window . innerHeight || document . documentElement . clientHeight ;
88+
89+ let left : number ;
90+ let right : number ;
91+ let top : number ;
92+ let bottom : number ;
93+
94+ if ( anchorRect . width >= flyoutRect . width ) {
95+ left = 0 ;
96+ } else {
97+ const centerOffset = flyoutRect . width / 2 - anchorRect . width / 2 ;
98+
99+ if ( anchorRect . left - centerOffset < 0 ) {
100+ left = - anchorRect . left ;
101+ } else {
102+ left = - centerOffset ;
103+ } // todo check if offscreen to the right and move left
104+ }
105+
106+ flyout . style . left = left ? `${ left } px` : '' ;
107+ flyout . style . right = right ? `${ right } px` : '' ;
108+ flyout . style . top = top ? `${ top } px` : '' ;
109+ flyout . style . bottom = bottom ? `${ bottom } px` : '' ;
110+ }
111+ }
112+
87113 /**
88114 * Invoked on each update to perform rendering tasks. This method must return
89115 * a lit-html TemplateResult. Setting properties inside this method will *not*
90116 * trigger the element to update.
91117 */
92118 protected render ( ) {
93119 return html `
94- < div
95- class ="root "
96- @mouseenter =${ this . _handleMouseEnter }
97- @mouseleave =${ this . _handleMouseLeave }
98- @click=${ this . _handleMouseClick }
99- >
100- < slot > </ slot >
101- < slot name ="flyout "> </ slot >
120+ < div class ="root ">
121+ < div class ="anchor ">
122+ < slot > </ slot >
123+ </ div >
124+ ${ this . renderFlyout ( ) }
102125 </ div >
103126 ` ;
104127 }
105128
106- private _handleMouseClick ( ) {
107- if ( this . personCardInteraction === PersonCardInteraction . click && ! this . _isPersonCardVisible ) {
108- this . _showPersonCard ( ) ;
109- } else {
110- this . _hidePersonCard ( ) ;
111- }
112- }
113-
114- private _handleMouseEnter ( e : MouseEvent ) {
115- if ( this . personCardInteraction !== PersonCardInteraction . hover ) {
129+ private renderFlyout ( ) {
130+ if ( ! this . isOpen && ! this . renderedOnce ) {
116131 return ;
117132 }
118133
119- clearTimeout ( this . _mouseEnterTimeout ) ;
120- clearTimeout ( this . _mouseLeaveTimeout ) ;
121- this . _mouseEnterTimeout = setTimeout ( this . _showPersonCard . bind ( this ) , 500 ) ;
122- }
134+ this . renderedOnce = true ;
135+
136+ const classes = {
137+ flyout : true ,
138+ visible : this . isOpen
139+ } ;
123140
124- private _handleMouseLeave ( e : MouseEvent ) {
125- clearTimeout ( this . _mouseEnterTimeout ) ;
126- clearTimeout ( this . _mouseLeaveTimeout ) ;
127- this . _mouseLeaveTimeout = setTimeout ( this . _hidePersonCard . bind ( this ) , 500 ) ;
141+ return html `
142+ < div class =${ classMap ( classes ) } >
143+ < slot name ="flyout "> </ slot >
144+ </ div >
145+ ` ;
128146 }
129147
130148 private _showPersonCard ( ) {
0 commit comments