matcha-components 20.198.0 → 20.199.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -331,7 +331,7 @@ class MatchaPanelComponent {
331
331
  const viewportWidth = window.innerWidth;
332
332
  const margin = 10;
333
333
  // Posicionamento lateral (para submenus)
334
- if (this.placement === 'right' || this.placement === 'left') {
334
+ if (this.placement === 'side') {
335
335
  return this.calculateSidePosition(rect, viewportWidth, viewportHeight, margin);
336
336
  }
337
337
  let top;
@@ -341,6 +341,13 @@ class MatchaPanelComponent {
341
341
  let maxHeight = this.maxHeight;
342
342
  let placement = 'bottom';
343
343
  let actualHeight = 0;
344
+ // Para max-content, medir a largura real renderizada do painel
345
+ if (this.widthMode === 'max-content' && this.paneRef) {
346
+ const panelWidth = this.paneRef.nativeElement.scrollWidth;
347
+ if (panelWidth > width) {
348
+ width = panelWidth;
349
+ }
350
+ }
344
351
  // Determinar se deve abrir para cima ou para baixo
345
352
  const spaceBelow = viewportHeight - rect.bottom - margin;
346
353
  const spaceAbove = rect.top - margin;
@@ -366,10 +373,11 @@ class MatchaPanelComponent {
366
373
  }
367
374
  // Posicionamento horizontal: alinhar à esquerda do trigger
368
375
  left = rect.left;
369
- // Garantir que não saia da tela horizontalmente
376
+ // Se o painel ultrapassa a tela pela direita, alinhar pela direita do trigger
370
377
  if (left + width > viewportWidth - margin) {
371
- left = viewportWidth - width - margin;
378
+ left = rect.right - width;
372
379
  }
380
+ // Se ainda ultrapassa pela esquerda, empurrar para a margem
373
381
  if (left < margin) {
374
382
  left = margin;
375
383
  width = Math.min(width, viewportWidth - 2 * margin);
@@ -383,21 +391,33 @@ class MatchaPanelComponent {
383
391
  }
384
392
  /**
385
393
  * Calcula posição lateral (para submenus multinível)
394
+ * Detecta automaticamente se deve abrir à direita ou à esquerda
386
395
  */
387
396
  calculateSidePosition(rect, viewportWidth, viewportHeight, margin) {
388
- const width = this.minWidth;
397
+ let width = this.minWidth;
389
398
  const maxHeight = this.maxHeight;
390
- // Tentar abrir à direita do trigger
399
+ // Para max-content, medir a largura real renderizada
400
+ if (this.widthMode === 'max-content' && this.paneRef) {
401
+ const panelWidth = this.paneRef.nativeElement.scrollWidth;
402
+ if (panelWidth > width) {
403
+ width = panelWidth;
404
+ }
405
+ }
406
+ // Auto-detectar: preferir direita, usar esquerda se não houver espaço
391
407
  const spaceRight = viewportWidth - rect.right - margin;
392
408
  const spaceLeft = rect.left - margin;
393
409
  let left;
394
- if (this.placement === 'left' || (spaceRight < width && spaceLeft >= width)) {
395
- // Abrir à esquerda
410
+ if (spaceRight >= width) {
411
+ left = rect.right + 2;
412
+ }
413
+ else if (spaceLeft >= width) {
396
414
  left = rect.left - width - 2;
397
415
  }
398
416
  else {
399
- // Abrir à direita
400
- left = rect.right + 2;
417
+ // Nenhum lado cabe: abrir no lado com mais espaço
418
+ left = spaceRight >= spaceLeft
419
+ ? rect.right + 2
420
+ : rect.left - width - 2;
401
421
  }
402
422
  // Posição vertical: alinhar o topo do submenu com o topo do item trigger
403
423
  let top = rect.top;
@@ -411,7 +431,7 @@ class MatchaPanelComponent {
411
431
  }
412
432
  // Garantir que não saia da tela horizontalmente
413
433
  if (left + width > viewportWidth - margin) {
414
- left = rect.left - width - 2;
434
+ left = viewportWidth - width - margin;
415
435
  }
416
436
  if (left < margin) {
417
437
  left = margin;
@@ -7457,7 +7477,7 @@ class MatchaMenuComponent {
7457
7477
  constructor(cdr) {
7458
7478
  this.cdr = cdr;
7459
7479
  this.placement = 'auto';
7460
- this._maxHeight = 240;
7480
+ this._maxHeight = 300;
7461
7481
  this._minWidth = 160;
7462
7482
  this.opened = new EventEmitter();
7463
7483
  this.closed = new EventEmitter();
@@ -7714,6 +7734,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImpor
7714
7734
  }] } });
7715
7735
 
7716
7736
  class MatchaSubmenuTriggerDirective {
7737
+ /** Detecta dispositivos sem hover (touch-primary) */
7738
+ get isTouch() {
7739
+ return window.matchMedia('(hover: none)').matches;
7740
+ }
7717
7741
  constructor(el) {
7718
7742
  this.el = el;
7719
7743
  this.hasSubmenuClass = true;
@@ -7727,14 +7751,38 @@ class MatchaSubmenuTriggerDirective {
7727
7751
  // Quando o mouse entra no painel do submenu, cancela TODA a cadeia de fechamento
7728
7752
  this.submenu.onPanelMouseEnter = () => this.cancelClose();
7729
7753
  // Quando o mouse sai do painel do submenu, agenda fechamento
7730
- // apenas se não houver submenus filhos abertos
7754
+ // apenas se não houver submenus filhos abertos (ignora em touch)
7731
7755
  this.submenu.onPanelMouseLeave = () => {
7732
- if (!this.submenu.hasOpenSubMenus()) {
7756
+ if (!this.isTouch && !this.submenu.hasOpenSubMenus()) {
7733
7757
  this.scheduleClose();
7734
7758
  }
7735
7759
  };
7736
7760
  }
7761
+ onClick(event) {
7762
+ if (!this.isTouch)
7763
+ return;
7764
+ // Impedir que o clique propague para o onContentClick do menu pai
7765
+ event.stopPropagation();
7766
+ if (!this.submenu || !this.parentMenu)
7767
+ return;
7768
+ // Toggle: se já está aberto, fecha; senão, abre
7769
+ if (this.submenu.open) {
7770
+ this.submenu.closePanel();
7771
+ this.parentMenu.unregisterSubMenu(this.submenu);
7772
+ return;
7773
+ }
7774
+ // Fechar outros submenus do mesmo nível
7775
+ this.parentMenu.closeOtherSubMenus(this.submenu);
7776
+ // Configurar relação pai/filho e abrir
7777
+ this.submenu.parentMenu = this.parentMenu;
7778
+ this.submenu.placement = 'side';
7779
+ this.submenu.openPanel(this.el.nativeElement);
7780
+ this.parentMenu.registerSubMenu(this.submenu);
7781
+ }
7737
7782
  onMouseEnter() {
7783
+ // Em touch, o submenu é controlado por click
7784
+ if (this.isTouch)
7785
+ return;
7738
7786
  // Cancelar qualquer fechamento pendente neste nível e nos pais
7739
7787
  this.cancelClose();
7740
7788
  if (this.parentMenu) {
@@ -7746,7 +7794,7 @@ class MatchaSubmenuTriggerDirective {
7746
7794
  this.parentMenu.closeOtherSubMenus(this.submenu);
7747
7795
  // Configurar relação pai/filho
7748
7796
  this.submenu.parentMenu = this.parentMenu;
7749
- this.submenu.placement = 'right';
7797
+ this.submenu.placement = 'side';
7750
7798
  // Abrir o submenu posicionado ao lado deste item
7751
7799
  if (!this.submenu.open) {
7752
7800
  this.submenu.openPanel(this.el.nativeElement);
@@ -7754,6 +7802,9 @@ class MatchaSubmenuTriggerDirective {
7754
7802
  }
7755
7803
  }
7756
7804
  onMouseLeave() {
7805
+ // Em touch, o submenu é controlado por click
7806
+ if (this.isTouch)
7807
+ return;
7757
7808
  // Agendar fechamento mas o cancelClose será chamado
7758
7809
  // se o mouse entrar no painel do submenu ou no item novamente
7759
7810
  this.scheduleClose();
@@ -7789,7 +7840,7 @@ class MatchaSubmenuTriggerDirective {
7789
7840
  }
7790
7841
  }
7791
7842
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: MatchaSubmenuTriggerDirective, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive }); }
7792
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.2", type: MatchaSubmenuTriggerDirective, isStandalone: false, selector: "[matchaSubmenuTriggerFor]", inputs: { submenu: ["matchaSubmenuTriggerFor", "submenu"], parentMenu: "parentMenu" }, host: { listeners: { "mouseenter": "onMouseEnter()", "mouseleave": "onMouseLeave()" }, properties: { "class.matcha-menu-item-has-submenu": "this.hasSubmenuClass" } }, ngImport: i0 }); }
7843
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.2", type: MatchaSubmenuTriggerDirective, isStandalone: false, selector: "[matchaSubmenuTriggerFor]", inputs: { submenu: ["matchaSubmenuTriggerFor", "submenu"], parentMenu: "parentMenu" }, host: { listeners: { "click": "onClick($event)", "mouseenter": "onMouseEnter()", "mouseleave": "onMouseLeave()" }, properties: { "class.matcha-menu-item-has-submenu": "this.hasSubmenuClass" } }, ngImport: i0 }); }
7793
7844
  }
7794
7845
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: MatchaSubmenuTriggerDirective, decorators: [{
7795
7846
  type: Directive,
@@ -7805,6 +7856,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImpor
7805
7856
  }], hasSubmenuClass: [{
7806
7857
  type: HostBinding,
7807
7858
  args: ['class.matcha-menu-item-has-submenu']
7859
+ }], onClick: [{
7860
+ type: HostListener,
7861
+ args: ['click', ['$event']]
7808
7862
  }], onMouseEnter: [{
7809
7863
  type: HostListener,
7810
7864
  args: ['mouseenter']