@seniorsistemas/angular-components 19.0.9 → 19.1.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.
Files changed (123) hide show
  1. package/breadcrumb/lib/breadcrumb/breadcrumb-models.d.ts +2 -0
  2. package/button/lib/button/button.component.d.ts +8 -2
  3. package/checkbox/lib/checkbox/checkbox.component.d.ts +5 -1
  4. package/dialog/lib/src/dialog/dialog.component.d.ts +7 -1
  5. package/esm2022/accordion/lib/accordion/components/accordion-panel/accordion-panel.component.mjs +2 -2
  6. package/esm2022/breadcrumb/lib/breadcrumb/breadcrumb-models.mjs +1 -1
  7. package/esm2022/breadcrumb/lib/breadcrumb/breadcrumb.component.mjs +3 -3
  8. package/esm2022/breadcrumb/lib/dynamic-breadcrumb/dynamic-breadcrumb.component.mjs +8 -6
  9. package/esm2022/button/lib/button/button.component.mjs +20 -8
  10. package/esm2022/checkbox/lib/checkbox/checkbox.component.mjs +8 -5
  11. package/esm2022/confirm-dialog/lib/popup-confirm-dialog/popup-confirm-dialog.component.mjs +2 -2
  12. package/esm2022/content-generator/lib/content-generator/content-generator.component.mjs +1 -1
  13. package/esm2022/dialog/lib/src/dialog/dialog.component.mjs +9 -3
  14. package/esm2022/dynamic-form/dynamic-form/components/grid/row/row.component.mjs +1 -1
  15. package/esm2022/dynamic-form/dynamic-form/components/lookup/lookup.component.mjs +2 -2
  16. package/esm2022/dynamic-form/dynamic-form/form-field/fields/bignumber/bignumber-field.component.mjs +1 -1
  17. package/esm2022/dynamic-form/dynamic-form/form-field/fields/boolean/boolean-radio-field/boolean-field.component.mjs +1 -1
  18. package/esm2022/dynamic-form/dynamic-form/form-field/fields/boolean/boolean-switch-field/boolean-switch-field.component.mjs +2 -2
  19. package/esm2022/dynamic-form/dynamic-form/form-field/fields/button-field/button-field.component.mjs +1 -1
  20. package/esm2022/dynamic-form/dynamic-form/form-field/fields/number/number-field.component.mjs +1 -1
  21. package/esm2022/dynamic-form/dynamic-form/form-field/fields/password/password-field.component.mjs +1 -1
  22. package/esm2022/dynamic-form/dynamic-form/form-field/fields/radio-button/radio-button-field.component.mjs +1 -1
  23. package/esm2022/dynamic-form/dynamic-form/form-field/fields/select/select-field.component.mjs +2 -2
  24. package/esm2022/dynamic-form/dynamic-form/form-field/fields/text/text-field.component.mjs +1 -1
  25. package/esm2022/empty-state/lib/empty-state/empty-state.component.mjs +1 -1
  26. package/esm2022/file-picker/lib/file-picker/file-picker.component.mjs +1 -1
  27. package/esm2022/global-search/lib/global-search/components/dropdown/global-search-dropdown-item.component.mjs +1 -1
  28. package/esm2022/global-search/lib/global-search/global-search.component.mjs +1 -1
  29. package/esm2022/help-popover/lib/help-popover/help-popover/help-popover.component.mjs +1 -1
  30. package/esm2022/image-cropper/lib/image-cropper/image-cropper.component.mjs +1 -1
  31. package/esm2022/inline-edit/lib/inline-edit/components/fields/inline-edit-number/inline-edit-number.component.mjs +1 -1
  32. package/esm2022/inline-edit/lib/inline-edit/components/inline-edit-item/inline-edit-item.component.mjs +1 -1
  33. package/esm2022/kanban/lib/kanban/components/kanban-column/kanban-column.component.mjs +1 -1
  34. package/esm2022/kanban/lib/kanban/components/kanban-item/kanban-item.component.mjs +1 -1
  35. package/esm2022/lib/locale/fallback.mjs +13 -2
  36. package/esm2022/navigation-button/lib/navigation-button/navigation-button.component.mjs +1 -1
  37. package/esm2022/object-card/lib/object-card/elements/field/object-card-field.component.mjs +1 -1
  38. package/esm2022/object-card/lib/object-card/elements/main/object-card-main.component.mjs +1 -1
  39. package/esm2022/paginator/lib/paginator/paginator.component.mjs +2 -2
  40. package/esm2022/picklist/lib/picklist/picklist.component.mjs +1 -1
  41. package/esm2022/profile-picture-picker/lib/profile-picture-picker/profile-picture-picker.component.mjs +1 -1
  42. package/esm2022/select/lib/select/components/select-option/select-option.component.mjs +3 -3
  43. package/esm2022/select/lib/select/select.component.mjs +132 -20
  44. package/esm2022/shared/lib/accessibility/paginator-accessibility.directive.mjs +182 -0
  45. package/esm2022/shared/lib/accessibility/table-checkbox-accessibility.directive.mjs +174 -0
  46. package/esm2022/shared/public-api.mjs +6 -4
  47. package/esm2022/switch/lib/switch/switch.component.mjs +19 -8
  48. package/esm2022/table/lib/table/table-paging/table-paging.component.mjs +1 -1
  49. package/esm2022/tiered-menu/lib/tiered-menu/components/tiered-menu/tiered-menu.component.mjs +18 -8
  50. package/esm2022/tiered-menu/lib/tiered-menu/components/tiered-menu-item/tiered-menu-item.component.mjs +1 -1
  51. package/esm2022/tiered-menu/lib/tiered-menu/services/tiered-menu.service.mjs +1 -1
  52. package/esm2022/tiered-menu/lib/tiered-menu/tiered-menu.directive.mjs +11 -3
  53. package/esm2022/tooltip/lib/tooltip/tooltip.component.mjs +17 -11
  54. package/esm2022/tooltip/lib/tooltip/tooltip.directive.mjs +108 -241
  55. package/esm2022/tooltip/lib/tooltip/tooltip.module.mjs +4 -6
  56. package/esm2022/topbar/lib/topbar/topbar.component.mjs +2 -2
  57. package/fesm2022/seniorsistemas-angular-components-accordion.mjs +1 -1
  58. package/fesm2022/seniorsistemas-angular-components-accordion.mjs.map +1 -1
  59. package/fesm2022/seniorsistemas-angular-components-breadcrumb.mjs +9 -7
  60. package/fesm2022/seniorsistemas-angular-components-breadcrumb.mjs.map +1 -1
  61. package/fesm2022/seniorsistemas-angular-components-button.mjs +19 -7
  62. package/fesm2022/seniorsistemas-angular-components-button.mjs.map +1 -1
  63. package/fesm2022/seniorsistemas-angular-components-checkbox.mjs +7 -4
  64. package/fesm2022/seniorsistemas-angular-components-checkbox.mjs.map +1 -1
  65. package/fesm2022/seniorsistemas-angular-components-confirm-dialog.mjs +1 -1
  66. package/fesm2022/seniorsistemas-angular-components-confirm-dialog.mjs.map +1 -1
  67. package/fesm2022/seniorsistemas-angular-components-content-generator.mjs +1 -1
  68. package/fesm2022/seniorsistemas-angular-components-content-generator.mjs.map +1 -1
  69. package/fesm2022/seniorsistemas-angular-components-dialog.mjs +8 -2
  70. package/fesm2022/seniorsistemas-angular-components-dialog.mjs.map +1 -1
  71. package/fesm2022/seniorsistemas-angular-components-dynamic-form.mjs +11 -11
  72. package/fesm2022/seniorsistemas-angular-components-dynamic-form.mjs.map +1 -1
  73. package/fesm2022/seniorsistemas-angular-components-empty-state.mjs +1 -1
  74. package/fesm2022/seniorsistemas-angular-components-empty-state.mjs.map +1 -1
  75. package/fesm2022/seniorsistemas-angular-components-file-picker.mjs +1 -1
  76. package/fesm2022/seniorsistemas-angular-components-file-picker.mjs.map +1 -1
  77. package/fesm2022/seniorsistemas-angular-components-global-search.mjs +2 -2
  78. package/fesm2022/seniorsistemas-angular-components-global-search.mjs.map +1 -1
  79. package/fesm2022/seniorsistemas-angular-components-help-popover.mjs +1 -1
  80. package/fesm2022/seniorsistemas-angular-components-help-popover.mjs.map +1 -1
  81. package/fesm2022/seniorsistemas-angular-components-image-cropper.mjs +1 -1
  82. package/fesm2022/seniorsistemas-angular-components-image-cropper.mjs.map +1 -1
  83. package/fesm2022/seniorsistemas-angular-components-inline-edit.mjs +2 -2
  84. package/fesm2022/seniorsistemas-angular-components-inline-edit.mjs.map +1 -1
  85. package/fesm2022/seniorsistemas-angular-components-kanban.mjs +2 -2
  86. package/fesm2022/seniorsistemas-angular-components-kanban.mjs.map +1 -1
  87. package/fesm2022/seniorsistemas-angular-components-navigation-button.mjs +1 -1
  88. package/fesm2022/seniorsistemas-angular-components-navigation-button.mjs.map +1 -1
  89. package/fesm2022/seniorsistemas-angular-components-object-card.mjs +2 -2
  90. package/fesm2022/seniorsistemas-angular-components-object-card.mjs.map +1 -1
  91. package/fesm2022/seniorsistemas-angular-components-paginator.mjs +1 -1
  92. package/fesm2022/seniorsistemas-angular-components-paginator.mjs.map +1 -1
  93. package/fesm2022/seniorsistemas-angular-components-picklist.mjs +1 -1
  94. package/fesm2022/seniorsistemas-angular-components-picklist.mjs.map +1 -1
  95. package/fesm2022/seniorsistemas-angular-components-profile-picture-picker.mjs +1 -1
  96. package/fesm2022/seniorsistemas-angular-components-profile-picture-picker.mjs.map +1 -1
  97. package/fesm2022/seniorsistemas-angular-components-select.mjs +133 -21
  98. package/fesm2022/seniorsistemas-angular-components-select.mjs.map +1 -1
  99. package/fesm2022/seniorsistemas-angular-components-shared.mjs +354 -2
  100. package/fesm2022/seniorsistemas-angular-components-shared.mjs.map +1 -1
  101. package/fesm2022/seniorsistemas-angular-components-switch.mjs +18 -7
  102. package/fesm2022/seniorsistemas-angular-components-switch.mjs.map +1 -1
  103. package/fesm2022/seniorsistemas-angular-components-table.mjs +1 -1
  104. package/fesm2022/seniorsistemas-angular-components-table.mjs.map +1 -1
  105. package/fesm2022/seniorsistemas-angular-components-tiered-menu.mjs +26 -8
  106. package/fesm2022/seniorsistemas-angular-components-tiered-menu.mjs.map +1 -1
  107. package/fesm2022/seniorsistemas-angular-components-tooltip.mjs +125 -254
  108. package/fesm2022/seniorsistemas-angular-components-tooltip.mjs.map +1 -1
  109. package/fesm2022/seniorsistemas-angular-components-topbar.mjs +2 -2
  110. package/fesm2022/seniorsistemas-angular-components-topbar.mjs.map +1 -1
  111. package/fesm2022/seniorsistemas-angular-components.mjs +12 -1
  112. package/fesm2022/seniorsistemas-angular-components.mjs.map +1 -1
  113. package/package.json +1 -1
  114. package/select/lib/select/select.component.d.ts +23 -2
  115. package/shared/lib/accessibility/paginator-accessibility.directive.d.ts +30 -0
  116. package/shared/lib/accessibility/table-checkbox-accessibility.directive.d.ts +46 -0
  117. package/shared/public-api.d.ts +7 -5
  118. package/switch/lib/switch/switch.component.d.ts +9 -5
  119. package/tiered-menu/lib/tiered-menu/components/tiered-menu/tiered-menu.component.d.ts +1 -0
  120. package/tiered-menu/lib/tiered-menu/tiered-menu.directive.d.ts +4 -2
  121. package/tooltip/lib/tooltip/tooltip.component.d.ts +13 -7
  122. package/tooltip/lib/tooltip/tooltip.directive.d.ts +27 -40
  123. package/tooltip/lib/tooltip/tooltip.module.d.ts +3 -4
@@ -1,28 +1,34 @@
1
+ import { Overlay } from '@angular/cdk/overlay';
2
+ import { ComponentPortal } from '@angular/cdk/portal';
1
3
  import * as i0 from '@angular/core';
2
- import { Component, input, Directive, Input, HostListener, NgModule } from '@angular/core';
3
- import { getElementPositionInfo, getElementLeftoverContentAvailable, isNullOrUndefined } from '@seniorsistemas/angular-components/utils';
4
- import * as i1 from '@angular/common';
5
- import { CommonModule } from '@angular/common';
6
- import * as i1$1 from '@seniorsistemas/angular-components/common';
4
+ import { input, Component, inject, ElementRef, Renderer2, Directive, HostListener, NgModule } from '@angular/core';
5
+ import { DebounceUtils } from '@seniorsistemas/angular-components/common';
6
+ import { NgClass } from '@angular/common';
7
7
 
8
+ /**
9
+ * @description Componente de apresentação do tooltip. Utilizado internamente pela diretiva `TooltipDirective`.
10
+ * O posicionamento é gerenciado pelo CDK Overlay via `TooltipDirective`.
11
+ */
8
12
  class TooltipComponent {
9
- tooltip = '';
10
- position = 'top';
11
- left = 0;
12
- top = 0;
13
- visible = false;
14
- escape = false;
13
+ /** @description Texto ou HTML a ser exibido no tooltip. */
14
+ tooltip = input('');
15
+ /** @description Posição do tooltip — usada para renderizar a seta no lado correto. */
16
+ position = input('top');
17
+ /** @description Controla a visibilidade (opacidade) do tooltip via transição CSS. */
18
+ visible = input(false);
19
+ /** @description Quando `true`, o conteúdo é renderizado como texto puro (escapa HTML). */
20
+ escape = input(false);
15
21
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TooltipComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
16
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: TooltipComponent, selector: "ng-component", ngImport: i0, template: "<div\n id=\"tooltip\"\n class=\"tooltip\"\n [ngClass]=\"['tooltip--' + position]\"\n [class.tooltip--visible]=\"visible\"\n [ngStyle]=\"{\n left: left + 'px',\n top: top + 'px',\n }\"\n>\n @if (escape) {\n <span class=\"tooltip__content\">\n {{ tooltip }}\n </span>\n } @else {\n <span\n class=\"tooltip__content\"\n [innerHTML]=\"tooltip\"\n >\n </span>\n }\n</div>\n", styles: [".tooltip{background-color:#000;border-radius:2px;color:#fff;font-family:Open Sans,sans-serif;font-size:14px;font-weight:400;line-height:21px;opacity:0;padding:8px;position:fixed;transform:translate(-50%);text-align:center;max-width:220px;word-wrap:break-word;z-index:99999;position:absolute}.tooltip--visible{opacity:1;transition:opacity .3s}.tooltip:before{content:\"\";height:0;position:absolute;width:0}.tooltip--bottom{margin-top:5px;transform:translate(-50%)}.tooltip--bottom:before{border:5px solid transparent;border-bottom:5px solid black;left:calc(50% - 5px);top:-10px}.tooltip--top{margin-bottom:5px;transform:translate(-50%,-100%)}.tooltip--top:before{border:5px solid transparent;border-top:5px solid black;left:calc(50% - 5px);bottom:-10px}.tooltip--left{margin-right:28px;transform:translate(calc(-100% - 7px),-50%)}.tooltip--left:before{border:5px solid transparent;border-left:5px solid black;right:-10px;bottom:calc(50% - 5px)}.tooltip--right{margin-left:7px;transform:translateY(-50%)}.tooltip--right:before{border:5px solid transparent;border-right:5px solid black;left:-10px;bottom:calc(50% - 5px)}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
22
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: TooltipComponent, isStandalone: true, selector: "s-tooltip", inputs: { tooltip: { classPropertyName: "tooltip", publicName: "tooltip", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, visible: { classPropertyName: "visible", publicName: "visible", isSignal: true, isRequired: false, transformFunction: null }, escape: { classPropertyName: "escape", publicName: "escape", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div\n class=\"tooltip relative max-w-[220px] break-words rounded-xsmall bg-grayscale-100 p-2 text-center font-open-sans text-sm font-normal leading-normal text-grayscale-0 transition-opacity duration-300\"\n [class.opacity-0]=\"!visible()\"\n [class.opacity-100]=\"visible()\"\n [class.tooltip--visible]=\"visible()\"\n [ngClass]=\"'tooltip--' + position()\"\n>\n @if (escape()) {\n <span class=\"tooltip__content\">\n {{ tooltip() }}\n </span>\n } @else {\n <span\n class=\"tooltip__content\"\n [innerHTML]=\"tooltip()\"\n >\n </span>\n }\n</div>\n\n", styles: [".tooltip--top:before,.tooltip--bottom:before,.tooltip--left:before,.tooltip--right:before{content:\"\";height:0;position:absolute;width:0}.tooltip--bottom:before{border:5px solid transparent;border-bottom:5px solid #0E1119;left:calc(50% - 5px);top:-10px}.tooltip--top:before{border:5px solid transparent;border-top:5px solid #0E1119;left:calc(50% - 5px);bottom:-10px}.tooltip--left:before{border:5px solid transparent;border-left:5px solid #0E1119;right:-10px;bottom:calc(50% - 5px)}.tooltip--right:before{border:5px solid transparent;border-right:5px solid #0E1119;left:-10px;bottom:calc(50% - 5px)}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
17
23
  }
18
24
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TooltipComponent, decorators: [{
19
25
  type: Component,
20
- args: [{ template: "<div\n id=\"tooltip\"\n class=\"tooltip\"\n [ngClass]=\"['tooltip--' + position]\"\n [class.tooltip--visible]=\"visible\"\n [ngStyle]=\"{\n left: left + 'px',\n top: top + 'px',\n }\"\n>\n @if (escape) {\n <span class=\"tooltip__content\">\n {{ tooltip }}\n </span>\n } @else {\n <span\n class=\"tooltip__content\"\n [innerHTML]=\"tooltip\"\n >\n </span>\n }\n</div>\n", styles: [".tooltip{background-color:#000;border-radius:2px;color:#fff;font-family:Open Sans,sans-serif;font-size:14px;font-weight:400;line-height:21px;opacity:0;padding:8px;position:fixed;transform:translate(-50%);text-align:center;max-width:220px;word-wrap:break-word;z-index:99999;position:absolute}.tooltip--visible{opacity:1;transition:opacity .3s}.tooltip:before{content:\"\";height:0;position:absolute;width:0}.tooltip--bottom{margin-top:5px;transform:translate(-50%)}.tooltip--bottom:before{border:5px solid transparent;border-bottom:5px solid black;left:calc(50% - 5px);top:-10px}.tooltip--top{margin-bottom:5px;transform:translate(-50%,-100%)}.tooltip--top:before{border:5px solid transparent;border-top:5px solid black;left:calc(50% - 5px);bottom:-10px}.tooltip--left{margin-right:28px;transform:translate(calc(-100% - 7px),-50%)}.tooltip--left:before{border:5px solid transparent;border-left:5px solid black;right:-10px;bottom:calc(50% - 5px)}.tooltip--right{margin-left:7px;transform:translateY(-50%)}.tooltip--right:before{border:5px solid transparent;border-right:5px solid black;left:-10px;bottom:calc(50% - 5px)}\n"] }]
26
+ args: [{ selector: 's-tooltip', standalone: true, imports: [NgClass], template: "<div\n class=\"tooltip relative max-w-[220px] break-words rounded-xsmall bg-grayscale-100 p-2 text-center font-open-sans text-sm font-normal leading-normal text-grayscale-0 transition-opacity duration-300\"\n [class.opacity-0]=\"!visible()\"\n [class.opacity-100]=\"visible()\"\n [class.tooltip--visible]=\"visible()\"\n [ngClass]=\"'tooltip--' + position()\"\n>\n @if (escape()) {\n <span class=\"tooltip__content\">\n {{ tooltip() }}\n </span>\n } @else {\n <span\n class=\"tooltip__content\"\n [innerHTML]=\"tooltip()\"\n >\n </span>\n }\n</div>\n\n", styles: [".tooltip--top:before,.tooltip--bottom:before,.tooltip--left:before,.tooltip--right:before{content:\"\";height:0;position:absolute;width:0}.tooltip--bottom:before{border:5px solid transparent;border-bottom:5px solid #0E1119;left:calc(50% - 5px);top:-10px}.tooltip--top:before{border:5px solid transparent;border-top:5px solid #0E1119;left:calc(50% - 5px);bottom:-10px}.tooltip--left:before{border:5px solid transparent;border-left:5px solid #0E1119;right:-10px;bottom:calc(50% - 5px)}.tooltip--right:before{border:5px solid transparent;border-right:5px solid #0E1119;left:-10px;bottom:calc(50% - 5px)}\n"] }]
21
27
  }] });
22
28
 
23
29
  /**
24
30
  * @description Diretiva que exibe um tooltip (dica de ferramenta) flutuante ao interagir com o elemento hospedeiro.
25
- * Posiciona-se automaticamente considerando o espaço disponível na tela.
31
+ * Posiciona-se automaticamente considerando o espaço disponível na tela, utilizando o CDK Overlay.
26
32
  * Suporta eventos de hover, click e focus, além de comportamentos customizados para mobile.
27
33
  *
28
34
  * @example
@@ -33,33 +39,28 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
33
39
  * @category Overlay
34
40
  */
35
41
  class TooltipDirective {
36
- elementRef;
37
- appRef;
38
- debounceUtils;
39
- renderer;
40
- viewContainerRef;
41
42
  /**
42
43
  * @description Texto exibido no tooltip. Quando vazio ou `undefined`, o tooltip não é renderizado.
43
44
  */
44
- tooltip;
45
+ tooltip = input(undefined, { alias: 'sTooltip' });
45
46
  /**
46
47
  * @description Posição preferencial do tooltip em relação ao elemento hospedeiro.
47
48
  * O tooltip se reposiciona automaticamente se não houver espaço suficiente.
48
49
  *
49
50
  * @default 'top'
50
51
  */
51
- tooltipPosition = 'top';
52
+ tooltipPosition = input('top');
52
53
  /**
53
54
  * @description Tempo em milissegundos antes do tooltip aparecer após o evento de ativação.
54
55
  *
55
56
  * @default 500
56
57
  */
57
- showDelay = 500;
58
+ showDelay = input(500);
58
59
  /**
59
60
  * @description Tempo em milissegundos que o tooltip permanece visível após aparecer.
60
61
  * Quando não informado, o tooltip permanece até o usuário sair do elemento.
61
62
  */
62
- displayTime;
63
+ displayTime = input(undefined);
63
64
  /**
64
65
  * @description Evento do elemento hospedeiro que dispara a exibição do tooltip.
65
66
  * - `'hover'`: exibe ao passar o mouse (padrão).
@@ -68,20 +69,20 @@ class TooltipDirective {
68
69
  *
69
70
  * @default 'hover'
70
71
  */
71
- tooltipEvent = 'hover';
72
+ tooltipEvent = input('hover');
72
73
  /**
73
74
  * @description Quando `true`, o conteúdo HTML do tooltip é escapado antes de ser renderizado.
74
75
  *
75
76
  * @default false
76
77
  */
77
- escape = false;
78
+ escape = input(false);
78
79
  /**
79
80
  * @description Quando `false`, o tooltip nunca é exibido, mesmo que haja interação do usuário.
80
81
  * Útil para desabilitar tooltips dinamicamente.
81
82
  *
82
83
  * @default true
83
84
  */
84
- visible = true;
85
+ visible = input(true);
85
86
  /**
86
87
  * @description Comportamento do tooltip em dispositivos móveis (touch).
87
88
  * - `'pressing'`: exibe ao pressionar e manter o toque (padrão).
@@ -89,11 +90,11 @@ class TooltipDirective {
89
90
  *
90
91
  * @default 'pressing'
91
92
  */
92
- mobileBehavior = 'pressing';
93
+ mobileBehavior = input('pressing');
93
94
  /**
94
95
  * @description Referência a um input HTML para sincronizar a exibição do tooltip com o foco no campo.
95
96
  */
96
- focusedInputRef = null;
97
+ focusedInputRef = input(null);
97
98
  /**
98
99
  * @description Quando `true`, o tooltip só é exibido se o texto do elemento estiver truncado (overflow).
99
100
  * Útil para cells de tabela ou elementos com `text-overflow: ellipsis`.
@@ -101,20 +102,17 @@ class TooltipDirective {
101
102
  * @default false
102
103
  */
103
104
  checkTruncatedText = input(false);
105
+ elementRef = inject(ElementRef);
106
+ overlay = inject(Overlay);
107
+ debounceUtils = inject(DebounceUtils);
108
+ renderer = inject(Renderer2);
109
+ overlayRef = null;
104
110
  componentRef = null;
111
+ positionChangeSubscription = null;
105
112
  showTimeout;
106
113
  touchTimeout;
107
- tooltipDivElement = null;
108
- debounceCreateTooltipFunction;
109
114
  tooltipCreatedByFocus = false;
110
- constructor(elementRef, appRef, debounceUtils, renderer, viewContainerRef) {
111
- this.elementRef = elementRef;
112
- this.appRef = appRef;
113
- this.debounceUtils = debounceUtils;
114
- this.renderer = renderer;
115
- this.viewContainerRef = viewContainerRef;
116
- this.debounceCreateTooltipFunction = this.debounceUtils.debounceLeading(() => this._createTooltip(true, true));
117
- }
115
+ debounceCreateTooltipFunction = this.debounceUtils.debounceLeading(() => this._createTooltip(true, true));
118
116
  ngOnInit() {
119
117
  this.validatePosition();
120
118
  this.updateTooltipVisibilityWhenFocusOnInput();
@@ -122,254 +120,147 @@ class TooltipDirective {
122
120
  ngOnDestroy() {
123
121
  this.destroy();
124
122
  }
125
- /**
126
- * Manipula a visibilidade do tooltip quando houver uma referência de input.
127
- */
128
- updateTooltipVisibilityWhenFocusOnInput() {
129
- if (this.focusedInputRef) {
130
- const inputFocus = this.focusedInputRef;
131
- const icon = this.getIconFromFocusedInput();
132
- this.renderer.listen(inputFocus, 'focus', () => {
133
- if (icon) {
134
- this._createTooltip(false, false);
135
- this.tooltipCreatedByFocus = true;
136
- }
137
- });
138
- this.renderer.listen(inputFocus, 'blur', () => {
139
- if (icon) {
140
- this.removeTooltip(icon);
141
- this.destroy();
142
- this.tooltipCreatedByFocus = false;
143
- }
144
- });
145
- }
146
- }
147
- /**
148
- * Obtém o elemento do ícone associado ao label do input em focus.
149
- * @returns O ícone do input em focus.
150
- */
151
- getIconFromFocusedInput() {
152
- return this.elementRef.nativeElement;
153
- }
154
- /**
155
- * Remove o tooltip associado ao ícone do input em focus.
156
- * @param icon O ícone do input em focus.
157
- */
158
- removeTooltip(icon) {
159
- const tooltip = icon.querySelector('.tooltip');
160
- if (tooltip) {
161
- tooltip.remove();
162
- }
163
- }
164
123
  // whenever the component with the tooltip is clicked I destroy the tooltip.
165
124
  // whenever a key is pressed on the component with the tooltip I destroy the tooltip.
166
125
  onClick() {
167
- if (this.tooltipEvent === 'hover' &&
126
+ if (this.tooltipEvent() === 'hover' &&
168
127
  !navigator.userAgent.match(/Android/i) &&
169
128
  !navigator.userAgent.match(/iPhone/i)) {
170
129
  this.destroy();
171
130
  }
172
131
  }
173
132
  onFocus() {
174
- if (this.tooltipEvent === 'focus') {
133
+ if (this.tooltipEvent() === 'focus') {
175
134
  this._createTooltip(true, true);
176
135
  }
177
136
  }
178
137
  onBlur() {
179
- if (this.tooltipEvent === 'focus') {
138
+ if (this.tooltipEvent() === 'focus') {
180
139
  this.destroy();
181
140
  }
182
141
  }
183
142
  onMouseEnter() {
184
- if (this.tooltipEvent === 'hover' || this.focusedInputRef) {
143
+ if (this.tooltipEvent() === 'hover' || this.focusedInputRef()) {
185
144
  this.debounceCreateTooltipFunction();
186
145
  }
187
146
  }
188
147
  onMouseLeave() {
189
- if ((this.tooltipEvent === 'hover' || this.focusedInputRef) && !this.tooltipCreatedByFocus) {
148
+ if ((this.tooltipEvent() === 'hover' || this.focusedInputRef()) && !this.tooltipCreatedByFocus) {
190
149
  this.destroy();
191
150
  }
192
151
  }
193
152
  onTouchStart() {
194
- if (this.tooltipEvent === 'hover') {
153
+ if (this.tooltipEvent() === 'hover') {
195
154
  window.clearTimeout(this.touchTimeout);
196
- const _delay = this.mobileBehavior === 'pressing' ? this.showDelay : 0;
155
+ const delay = this.mobileBehavior() === 'pressing' ? this.showDelay() : 0;
197
156
  this.touchTimeout = window.setTimeout(() => {
198
157
  this._createTooltip(true, true);
199
- }, _delay);
158
+ }, delay);
200
159
  }
201
160
  }
202
161
  onTouchEnd() {
203
- if (this.tooltipEvent === 'hover') {
204
- if (this.mobileBehavior === 'pressing') {
205
- window.clearTimeout(this.touchTimeout);
206
- this.destroy();
207
- }
162
+ if (this.tooltipEvent() === 'hover' && this.mobileBehavior() === 'pressing') {
163
+ window.clearTimeout(this.touchTimeout);
164
+ this.destroy();
208
165
  }
209
166
  }
210
167
  validatePosition() {
211
- const containsPosition = ['top', 'right', 'bottom', 'left'].includes(this.tooltipPosition);
168
+ const containsPosition = ['top', 'right', 'bottom', 'left'].includes(this.tooltipPosition());
212
169
  if (!containsPosition) {
213
- this.tooltipPosition = 'top';
214
- throw new Error(`Tooltip ${this.tooltipPosition} position is unexpected`);
170
+ throw new Error(`Tooltip position "${this.tooltipPosition()}" is unexpected`);
215
171
  }
216
172
  }
217
- getDomElement() {
218
- this.componentRef = this.viewContainerRef.createComponent(TooltipComponent);
219
- return this.componentRef.location.nativeElement;
173
+ /**
174
+ * Manipula a visibilidade do tooltip quando houver uma referência de input.
175
+ */
176
+ updateTooltipVisibilityWhenFocusOnInput() {
177
+ const inputRef = this.focusedInputRef();
178
+ if (!inputRef)
179
+ return;
180
+ this.renderer.listen(inputRef, 'focus', () => {
181
+ this._createTooltip(false, false);
182
+ this.tooltipCreatedByFocus = true;
183
+ });
184
+ this.renderer.listen(inputRef, 'blur', () => {
185
+ this.destroy();
186
+ this.tooltipCreatedByFocus = false;
187
+ });
220
188
  }
221
189
  _createTooltip(useShowDelay = false, autoDestroy = true) {
222
- const hasText = (this.tooltip || '').length > 0;
223
- const hasComponentRef = this.componentRef !== null;
224
- if (!hasText || hasComponentRef) {
190
+ const tooltipText = this.tooltip() ?? '';
191
+ if (!tooltipText.length || this.overlayRef !== null)
225
192
  return;
226
- }
227
- const blockIfIsNotTruncatedContent = this.checkTruncatedText() ? !this.contentIsTruncated : false;
228
- if (blockIfIsNotTruncatedContent) {
193
+ if (this.checkTruncatedText() && !this.contentIsTruncated)
229
194
  return;
230
- }
231
- const domElement = this.getDomElement();
232
- document.body.appendChild(domElement);
233
- this.tooltipDivElement = domElement.querySelector('.tooltip');
234
- this.setTooltipComponentProperties();
235
- const _showDelay = useShowDelay ? this.showDelay : 0;
236
- setTimeout(() => {
237
- this.showTooltip();
238
- }, _showDelay);
239
- this.renderer.listen(window, 'scroll', () => {
240
- this.setTooltipPositionProperty();
195
+ const positionStrategy = this.buildPositionStrategy();
196
+ const scrollStrategy = this.overlay.scrollStrategies.reposition();
197
+ this.overlayRef = this.overlay.create({ positionStrategy, scrollStrategy });
198
+ const portal = new ComponentPortal(TooltipComponent);
199
+ this.componentRef = this.overlayRef.attach(portal);
200
+ this.componentRef.setInput('tooltip', tooltipText);
201
+ this.componentRef.setInput('escape', this.escape());
202
+ this.componentRef.setInput('position', this.tooltipPosition());
203
+ this.positionChangeSubscription = positionStrategy.positionChanges.subscribe((change) => {
204
+ const mappedPosition = this.mapCdkPositionToTooltipPosition(change.connectionPair);
205
+ this.componentRef?.setInput('position', mappedPosition);
241
206
  });
242
- if (autoDestroy && this.displayTime) {
243
- setTimeout(() => {
207
+ const delay = useShowDelay ? this.showDelay() : 0;
208
+ this.showTimeout = window.setTimeout(() => {
209
+ this.componentRef?.setInput('visible', this.visible());
210
+ }, delay);
211
+ if (autoDestroy && this.displayTime()) {
212
+ window.setTimeout(() => {
244
213
  this.destroy();
245
- }, this.displayTime);
214
+ }, this.displayTime());
246
215
  }
247
216
  }
248
- showTooltip() {
249
- if (this.componentRef) {
250
- this.componentRef.instance.visible = this.visible;
251
- this.setTooltipPositionProperty();
252
- }
217
+ buildPositionStrategy() {
218
+ const preferred = this.tooltipPosition();
219
+ const allPositions = ['top', 'bottom', 'left', 'right'];
220
+ const orderedPositions = [preferred, ...allPositions.filter((p) => p !== preferred)];
221
+ return this.overlay
222
+ .position()
223
+ .flexibleConnectedTo(this.elementRef)
224
+ .withPositions(orderedPositions.map((p) => this.getConnectedPosition(p)))
225
+ .withFlexibleDimensions(false)
226
+ .withPush(false);
253
227
  }
254
- setTooltipPositionProperty() {
255
- if (!this.componentRef) {
256
- return;
257
- }
258
- const anchorSize = 5;
259
- const { left, right } = this.elementRef.nativeElement.getBoundingClientRect();
260
- const tooltipElementPosition = getElementPositionInfo(this.tooltipDivElement);
261
- const elementLeftover = getElementLeftoverContentAvailable(this.elementRef.nativeElement);
262
- const elementTriggerPosition = getElementPositionInfo(this.elementRef.nativeElement);
263
- const horizontalPositions = ['left', 'right'];
264
- const isPositionHorizontal = horizontalPositions.includes(this.tooltipPosition);
265
- const distanceToBorders = isPositionHorizontal
266
- ? tooltipElementPosition.elementWidth
267
- : tooltipElementPosition.elementHorizontalCenter;
268
- const canSetAtTop = elementLeftover.freeDistanceToTop > tooltipElementPosition.elementHeight;
269
- const canSetAtLeft = elementLeftover.freeDistanceToLeft > distanceToBorders;
270
- const canSetAtRight = elementLeftover.freeDistanceToRight > distanceToBorders;
271
- const canSetAtBottom = elementLeftover.freeDistanceToBottom > tooltipElementPosition.elementHeight;
272
- const topVertical = elementTriggerPosition.top + elementTriggerPosition.elementVerticalCenter;
273
- const checkTopPosition = () => {
274
- return canSetAtTop && canSetAtLeft && canSetAtRight;
228
+ getConnectedPosition(pos) {
229
+ const offset = 10;
230
+ const positionMap = {
231
+ top: { originX: 'center', originY: 'top', overlayX: 'center', overlayY: 'bottom', offsetY: -offset },
232
+ bottom: { originX: 'center', originY: 'bottom', overlayX: 'center', overlayY: 'top', offsetY: offset },
233
+ left: { originX: 'start', originY: 'center', overlayX: 'end', overlayY: 'center', offsetX: -offset },
234
+ right: { originX: 'end', originY: 'center', overlayX: 'start', overlayY: 'center', offsetX: offset },
275
235
  };
276
- const checkBottomPosition = () => {
277
- return canSetAtBottom && canSetAtLeft && canSetAtRight;
278
- };
279
- const checkLeftPosition = () => {
280
- return canSetAtLeft && canSetAtTop && canSetAtBottom;
281
- };
282
- const checkRightPosition = () => {
283
- return canSetAtRight && canSetAtTop && canSetAtBottom;
284
- };
285
- const setTopPosition = () => {
286
- return {
287
- left: left + (right - left) / 2,
288
- top: elementTriggerPosition.top - anchorSize,
289
- };
290
- };
291
- const setBottomPosition = () => {
292
- return {
293
- left: left + (right - left) / 2,
294
- top: elementTriggerPosition.top + elementTriggerPosition.elementHeight,
295
- };
296
- };
297
- const setLeftPosition = () => {
298
- return {
299
- left: left,
300
- top: topVertical,
301
- };
302
- };
303
- const setRightPosition = () => {
304
- return {
305
- left: right,
306
- top: topVertical,
307
- };
308
- };
309
- const positions = [
310
- {
311
- pos: 'top',
312
- check: checkTopPosition,
313
- set: setTopPosition,
314
- },
315
- {
316
- pos: 'bottom',
317
- check: checkBottomPosition,
318
- set: setBottomPosition,
319
- },
320
- {
321
- pos: 'left',
322
- check: checkLeftPosition,
323
- set: setLeftPosition,
324
- },
325
- {
326
- pos: 'right',
327
- check: checkRightPosition,
328
- set: setRightPosition,
329
- },
330
- ];
331
- const positionDefined = positions.find((position) => position.pos === this.tooltipPosition);
332
- let validPosition = positionDefined;
333
- const canUseDefinedPosition = positionDefined?.check();
334
- if (canUseDefinedPosition) {
335
- validPosition = positionDefined;
336
- }
337
- else if (!canUseDefinedPosition) {
338
- const validAlternativePosition = positions.find((position) => position.check());
339
- if (validAlternativePosition) {
340
- validPosition = validAlternativePosition;
341
- }
342
- }
343
- const _position = validPosition.set();
344
- const positionLeft = _position.left;
345
- const positionTop = _position.top;
346
- this.componentRef.instance.left = Math.round(positionLeft);
347
- this.componentRef.instance.top = Math.round(positionTop);
348
- this.componentRef.instance.position = validPosition.pos;
236
+ return positionMap[pos];
349
237
  }
350
- setTooltipComponentProperties() {
351
- if (!this.componentRef)
352
- return;
353
- this.componentRef.instance.tooltip = this.tooltip;
354
- this.componentRef.instance.escape = this.escape;
238
+ mapCdkPositionToTooltipPosition(pair) {
239
+ if (pair.overlayY === 'bottom')
240
+ return 'top';
241
+ if (pair.overlayY === 'top')
242
+ return 'bottom';
243
+ if (pair.overlayX === 'end')
244
+ return 'left';
245
+ return 'right';
355
246
  }
356
247
  destroy() {
357
- if (!isNullOrUndefined(this.componentRef)) {
358
- window.clearTimeout(this.showTimeout);
359
- this.appRef.detachView(this.componentRef.hostView);
360
- this.componentRef.destroy();
248
+ window.clearTimeout(this.showTimeout);
249
+ window.clearTimeout(this.touchTimeout);
250
+ this.positionChangeSubscription?.unsubscribe();
251
+ this.positionChangeSubscription = null;
252
+ if (this.overlayRef) {
253
+ this.overlayRef.dispose();
254
+ this.overlayRef = null;
361
255
  this.componentRef = null;
362
- this.tooltipDivElement = null;
363
256
  }
364
257
  }
365
258
  get contentIsTruncated() {
366
259
  const element = this.elementRef.nativeElement;
367
- const truncatedByVertical = element.scrollHeight > element.clientHeight;
368
- const truncatedByHorizontal = element.scrollWidth > element.clientWidth;
369
- return truncatedByHorizontal || truncatedByVertical;
260
+ return element.scrollHeight > element.clientHeight || element.scrollWidth > element.clientWidth;
370
261
  }
371
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TooltipDirective, deps: [{ token: i0.ElementRef }, { token: i0.ApplicationRef }, { token: i1$1.DebounceUtils }, { token: i0.Renderer2 }, { token: i0.ViewContainerRef }], target: i0.ɵɵFactoryTarget.Directive });
372
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "18.2.14", type: TooltipDirective, isStandalone: true, selector: "[sTooltip]", inputs: { tooltip: { classPropertyName: "tooltip", publicName: "sTooltip", isSignal: false, isRequired: false, transformFunction: null }, tooltipPosition: { classPropertyName: "tooltipPosition", publicName: "tooltipPosition", isSignal: false, isRequired: false, transformFunction: null }, showDelay: { classPropertyName: "showDelay", publicName: "showDelay", isSignal: false, isRequired: false, transformFunction: null }, displayTime: { classPropertyName: "displayTime", publicName: "displayTime", isSignal: false, isRequired: false, transformFunction: null }, tooltipEvent: { classPropertyName: "tooltipEvent", publicName: "tooltipEvent", isSignal: false, isRequired: false, transformFunction: null }, escape: { classPropertyName: "escape", publicName: "escape", isSignal: false, isRequired: false, transformFunction: null }, visible: { classPropertyName: "visible", publicName: "visible", isSignal: false, isRequired: false, transformFunction: null }, mobileBehavior: { classPropertyName: "mobileBehavior", publicName: "mobileBehavior", isSignal: false, isRequired: false, transformFunction: null }, focusedInputRef: { classPropertyName: "focusedInputRef", publicName: "focusedInputRef", isSignal: false, isRequired: false, transformFunction: null }, checkTruncatedText: { classPropertyName: "checkTruncatedText", publicName: "checkTruncatedText", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "click": "onClick()", "keydown": "onClick()", "focus": "onFocus()", "blur": "onBlur()", "mouseenter": "onMouseEnter()", "mouseleave": "onMouseLeave()", "wheel": "onMouseLeave()", "touchstart": "onTouchStart()", "touchend": "onTouchEnd()" } }, ngImport: i0 });
262
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TooltipDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
263
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "18.2.14", type: TooltipDirective, isStandalone: true, selector: "[sTooltip]", inputs: { tooltip: { classPropertyName: "tooltip", publicName: "sTooltip", isSignal: true, isRequired: false, transformFunction: null }, tooltipPosition: { classPropertyName: "tooltipPosition", publicName: "tooltipPosition", isSignal: true, isRequired: false, transformFunction: null }, showDelay: { classPropertyName: "showDelay", publicName: "showDelay", isSignal: true, isRequired: false, transformFunction: null }, displayTime: { classPropertyName: "displayTime", publicName: "displayTime", isSignal: true, isRequired: false, transformFunction: null }, tooltipEvent: { classPropertyName: "tooltipEvent", publicName: "tooltipEvent", isSignal: true, isRequired: false, transformFunction: null }, escape: { classPropertyName: "escape", publicName: "escape", isSignal: true, isRequired: false, transformFunction: null }, visible: { classPropertyName: "visible", publicName: "visible", isSignal: true, isRequired: false, transformFunction: null }, mobileBehavior: { classPropertyName: "mobileBehavior", publicName: "mobileBehavior", isSignal: true, isRequired: false, transformFunction: null }, focusedInputRef: { classPropertyName: "focusedInputRef", publicName: "focusedInputRef", isSignal: true, isRequired: false, transformFunction: null }, checkTruncatedText: { classPropertyName: "checkTruncatedText", publicName: "checkTruncatedText", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "click": "onClick()", "keydown": "onClick()", "focus": "onFocus()", "blur": "onBlur()", "mouseenter": "onMouseEnter()", "mouseleave": "onMouseLeave()", "wheel": "onMouseLeave()", "touchstart": "onTouchStart()", "touchend": "onTouchEnd()" } }, ngImport: i0 });
373
264
  }
374
265
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TooltipDirective, decorators: [{
375
266
  type: Directive,
@@ -377,26 +268,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
377
268
  selector: '[sTooltip]',
378
269
  standalone: true,
379
270
  }]
380
- }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.ApplicationRef }, { type: i1$1.DebounceUtils }, { type: i0.Renderer2 }, { type: i0.ViewContainerRef }], propDecorators: { tooltip: [{
381
- type: Input,
382
- args: ['sTooltip']
383
- }], tooltipPosition: [{
384
- type: Input
385
- }], showDelay: [{
386
- type: Input
387
- }], displayTime: [{
388
- type: Input
389
- }], tooltipEvent: [{
390
- type: Input
391
- }], escape: [{
392
- type: Input
393
- }], visible: [{
394
- type: Input
395
- }], mobileBehavior: [{
396
- type: Input
397
- }], focusedInputRef: [{
398
- type: Input
399
- }], onClick: [{
271
+ }], propDecorators: { onClick: [{
400
272
  type: HostListener,
401
273
  args: ['click']
402
274
  }, {
@@ -427,14 +299,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
427
299
 
428
300
  class TooltipModule {
429
301
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TooltipModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
430
- static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.14", ngImport: i0, type: TooltipModule, declarations: [TooltipComponent], imports: [CommonModule, TooltipDirective], exports: [TooltipDirective] });
431
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TooltipModule, imports: [CommonModule] });
302
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.14", ngImport: i0, type: TooltipModule, imports: [TooltipDirective, TooltipComponent], exports: [TooltipDirective] });
303
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TooltipModule });
432
304
  }
433
305
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TooltipModule, decorators: [{
434
306
  type: NgModule,
435
307
  args: [{
436
- imports: [CommonModule, TooltipDirective],
437
- declarations: [TooltipComponent],
308
+ imports: [TooltipDirective, TooltipComponent],
438
309
  exports: [TooltipDirective],
439
310
  }]
440
311
  }] });