1+ import { Component , Part , Prop } from '@pictogrammers/element' ;
2+
3+ import PgMenu from '../menu/menu' ;
4+ import PgOverlay from '../overlay/overlay' ;
5+
6+ import template from './overlayContextMenu.html' ;
7+ import style from './overlayContextMenu.css' ;
8+
9+ @Component ( {
10+ selector : 'pg-overlay-context-menu' ,
11+ template,
12+ style
13+ } )
14+ export default class PgOverlayContextMenu extends PgOverlay {
15+ @Part ( ) $overlay : HTMLDivElement ;
16+ @Part ( ) $menu : PgMenu ;
17+
18+ @Prop ( ) source : HTMLElement | null = null ;
19+ @Prop ( ) default : any = null ;
20+ @Prop ( ) items : any [ ] = [ ] ;
21+ @Prop ( ) value : any = null ;
22+
23+ render ( changes ) {
24+ if ( changes . items ) {
25+ if ( this . value !== null ) {
26+ this . items . forEach ( item => item . checked = false ) ;
27+ this . items . find ( item => item . value === this . value . value ) . checked = true ;
28+ }
29+ this . $menu . items = this . items ;
30+ }
31+ }
32+
33+ connectedCallback ( ) {
34+ this . $menu . addEventListener ( 'select' , this . #handleSelect. bind ( this ) ) ;
35+ this . $overlay . popover = 'auto' ;
36+ if ( this . source !== null ) {
37+ // @ts -ignore
38+ this . $overlay . showPopover ( {
39+ source : this . source
40+ } ) ;
41+ }
42+ this . $overlay . addEventListener ( 'toggle' , this . #toggle. bind ( this ) ) ;
43+ // Position
44+ const rect = this . source ?. getBoundingClientRect ( ) ;
45+ let x = 0 , y = 0 ;
46+ const value = this . value === null || typeof this . value !== 'object'
47+ ? this . value
48+ : this . value . value ;
49+ // value is an item in the items list
50+ const index = this . value === null
51+ ? - 1
52+ : this . items . findIndex ( x => x . value === value ) ;
53+ if ( index !== - 1 ) {
54+ const height = this . $menu . getItemHeight ( index ) ;
55+ // Overlap item
56+ y -= this . $menu . getItemOffset ( 0 , index ) ;
57+ if ( rect ?. height !== height && rect ?. height ) {
58+ y += ( rect . height - height ) / 2 ;
59+ }
60+ } else if ( this . items . length > 0 ) {
61+ // insert default if defined
62+ if ( this . default ) {
63+ this . default . checked = true ;
64+ this . $menu . items . unshift ( this . default ) ;
65+ }
66+ // focus first item
67+ const height = this . $menu . getItemHeight ( 0 ) ;
68+ y -= this . $menu . getItemOffset ( 0 , 0 ) ;
69+ if ( rect ?. height !== height && rect ?. height ) {
70+ y += ( rect . height - height ) / 2 ;
71+ }
72+ }
73+ // ToDo: update to CSS Variables
74+ this . $overlay . style . setProperty ( '--pg-overlay-menu-_x' , `${ x } px` ) ;
75+ this . $overlay . style . setProperty ( '--pg-overlay-menu-_y' , `${ y } px` ) ;
76+ // Focus
77+ this . $menu . focus ( index ) ;
78+ }
79+
80+ #toggle( e : ToggleEvent ) {
81+ if ( e . newState === 'closed' ) {
82+ this . close ( ) ;
83+ this . source ?. focus ( ) ;
84+ }
85+ }
86+
87+ disconnectedCallback ( ) {
88+ }
89+
90+ #handleSelect( e : any ) {
91+ e . detail . item . index = e . detail . index ;
92+ this . close ( e . detail . item ) ;
93+ this . source ?. focus ( ) ;
94+ }
95+ }
0 commit comments