@masterkeymaterial/ui 0.0.1 → 0.0.2

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 (141) hide show
  1. package/README.md +9 -59
  2. package/ng-package.json +10 -0
  3. package/package.json +5 -14
  4. package/src/elements/ui-button/ui-button.css +229 -0
  5. package/src/elements/ui-button/ui-button.html +12 -0
  6. package/src/elements/ui-button/ui-button.ts +133 -0
  7. package/src/elements/ui-check-box/ui-check-box.css +66 -0
  8. package/src/elements/ui-check-box/ui-check-box.html +5 -0
  9. package/src/elements/ui-check-box/ui-check-box.ts +65 -0
  10. package/src/elements/ui-chip/ui-chip.css +24 -0
  11. package/src/elements/ui-chip/ui-chip.html +3 -0
  12. package/src/elements/ui-chip/ui-chip.ts +25 -0
  13. package/src/elements/ui-drop-zone/ui-drop-zone.css +91 -0
  14. package/src/elements/ui-drop-zone/ui-drop-zone.html +8 -0
  15. package/src/elements/ui-drop-zone/ui-drop-zone.ts +153 -0
  16. package/src/elements/ui-file-list/ui-file-list.css +43 -0
  17. package/src/elements/ui-file-list/ui-file-list.html +17 -0
  18. package/src/elements/ui-file-list/ui-file-list.ts +22 -0
  19. package/src/elements/ui-list-errors/ui-list-errors.css +30 -0
  20. package/src/elements/ui-list-errors/ui-list-errors.html +10 -0
  21. package/src/elements/ui-list-errors/ui-list-errors.ts +14 -0
  22. package/src/elements/ui-loading/ui-loading.css +13 -0
  23. package/src/elements/ui-loading/ui-loading.html +1 -0
  24. package/src/elements/ui-loading/ui-loading.ts +10 -0
  25. package/src/elements/ui-menu/ui-menu.css +69 -0
  26. package/src/elements/ui-menu/ui-menu.html +20 -0
  27. package/src/elements/ui-menu/ui-menu.ts +267 -0
  28. package/src/elements/ui-procurar/ui-procurar.css +48 -0
  29. package/src/elements/ui-procurar/ui-procurar.html +14 -0
  30. package/src/elements/ui-procurar/ui-procurar.ts +82 -0
  31. package/src/elements/ui-progress/ui-progress.css +0 -0
  32. package/src/elements/ui-progress/ui-progress.html +1 -0
  33. package/src/elements/ui-progress/ui-progress.ts +15 -0
  34. package/src/elements/ui-select/ui-select.css +211 -0
  35. package/src/elements/ui-select/ui-select.html +46 -0
  36. package/src/elements/ui-select/ui-select.ts +482 -0
  37. package/src/elements/ui-slide/ui-slide.css +75 -0
  38. package/src/elements/ui-slide/ui-slide.html +7 -0
  39. package/src/elements/ui-slide/ui-slide.ts +61 -0
  40. package/src/fields/Base/BaseFieldsForm/BaseFieldsForm.component.ts +113 -0
  41. package/src/fields/Base/BaseFieldsValues/BaseFieldsValues.ts +112 -0
  42. package/src/fields/Formulario/Formulario.ts +1056 -0
  43. package/src/fields/Formulario/form-action/form-action.css +98 -0
  44. package/src/fields/Formulario/form-action/form-action.html +75 -0
  45. package/src/fields/Formulario/form-action/form-action.ts +187 -0
  46. package/src/fields/Formulario/form-controls/form-controls.css +108 -0
  47. package/src/fields/Formulario/form-controls/form-controls.html +105 -0
  48. package/src/fields/Formulario/form-controls/form-controls.ts +122 -0
  49. package/src/fields/Formulario/form-fase/form-fase.css +84 -0
  50. package/src/fields/Formulario/form-fase/form-fase.html +24 -0
  51. package/src/fields/Formulario/form-fase/form-fase.ts +157 -0
  52. package/src/fields/Formulario/form-filter/form-filter.css +50 -0
  53. package/src/fields/Formulario/form-filter/form-filter.html +25 -0
  54. package/src/fields/Formulario/form-filter/form-filter.ts +53 -0
  55. package/src/fields/Formulario/form-no-action/form-no-action.css +32 -0
  56. package/src/fields/Formulario/form-no-action/form-no-action.html +12 -0
  57. package/src/fields/Formulario/form-no-action/form-no-action.ts +21 -0
  58. package/src/fields/Formulario/formated-values/formated-values.css +104 -0
  59. package/src/fields/Formulario/formated-values/formated-values.html +15 -0
  60. package/src/fields/Formulario/formated-values/formated-values.ts +186 -0
  61. package/src/fields/Formulario/single-values/single-values.css +88 -0
  62. package/src/fields/Formulario/single-values/single-values.html +11 -0
  63. package/src/fields/Formulario/single-values/single-values.ts +65 -0
  64. package/src/fields/autocomplete/autocomplete.css +94 -0
  65. package/src/fields/autocomplete/autocomplete.html +38 -0
  66. package/src/fields/autocomplete/autocomplete.ts +294 -0
  67. package/src/fields/button/button.css +7 -0
  68. package/src/fields/button/button.html +19 -0
  69. package/src/fields/button/button.ts +38 -0
  70. package/src/fields/checkbox/checkbox.css +27 -0
  71. package/src/fields/checkbox/checkbox.html +20 -0
  72. package/src/fields/checkbox/checkbox.ts +44 -0
  73. package/src/fields/color/CirculoColorido/circulocolorido.css +50 -0
  74. package/src/fields/color/CirculoColorido/circulocolorido.html +8 -0
  75. package/src/fields/color/CirculoColorido/circulocolorido.ts +24 -0
  76. package/src/fields/color/color.css +15 -0
  77. package/src/fields/color/color.html +24 -0
  78. package/src/fields/color/color.ts +47 -0
  79. package/src/fields/date/date.html +19 -0
  80. package/src/fields/date/date.ts +29 -0
  81. package/src/fields/datetime/datetime.html +19 -0
  82. package/src/fields/datetime/datetime.ts +29 -0
  83. package/src/fields/display/display.css +7 -0
  84. package/src/fields/display/display.html +20 -0
  85. package/src/fields/display/display.ts +43 -0
  86. package/src/fields/editor/editor.css +51 -0
  87. package/src/fields/editor/editor.html +37 -0
  88. package/src/fields/editor/editor.ts +218 -0
  89. package/src/fields/email/email.html +19 -0
  90. package/src/fields/email/email.ts +29 -0
  91. package/src/fields/fields.css +180 -0
  92. package/src/fields/generic/generic.html +3 -0
  93. package/src/fields/generic/generic.ts +91 -0
  94. package/src/fields/hidden/hidden.html +3 -0
  95. package/src/fields/hidden/hidden.ts +20 -0
  96. package/src/fields/icon/icon.css +19 -0
  97. package/src/fields/icon/icon.html +27 -0
  98. package/src/fields/icon/icon.ts +31 -0
  99. package/src/fields/multifactor/multifactor.css +21 -0
  100. package/src/fields/multifactor/multifactor.html +39 -0
  101. package/src/fields/multifactor/multifactor.ts +106 -0
  102. package/src/fields/multikv/multikv.css +43 -0
  103. package/src/fields/multikv/multikv.html +47 -0
  104. package/src/fields/multikv/multikv.ts +88 -0
  105. package/src/fields/multitext/multitext.css +36 -0
  106. package/src/fields/multitext/multitext.html +38 -0
  107. package/src/fields/multitext/multitext.ts +75 -0
  108. package/src/fields/number/number.html +20 -0
  109. package/src/fields/number/number.ts +35 -0
  110. package/src/fields/password/password.html +23 -0
  111. package/src/fields/password/password.ts +37 -0
  112. package/src/fields/search/search.css +0 -0
  113. package/src/fields/search/search.html +19 -0
  114. package/src/fields/search/search.ts +54 -0
  115. package/src/fields/select/select.css +15 -0
  116. package/src/fields/select/select.html +18 -0
  117. package/src/fields/select/select.ts +52 -0
  118. package/src/fields/slide/slide.css +27 -0
  119. package/src/fields/slide/slide.html +20 -0
  120. package/src/fields/slide/slide.ts +45 -0
  121. package/src/fields/text/text.html +19 -0
  122. package/src/fields/text/text.ts +30 -0
  123. package/src/fields/textarea/textarea.css +4 -0
  124. package/src/fields/textarea/textarea.html +20 -0
  125. package/src/fields/textarea/textarea.ts +31 -0
  126. package/src/fields/time/time.html +19 -0
  127. package/src/fields/time/time.ts +29 -0
  128. package/src/fields/upload/upload.css +24 -0
  129. package/src/fields/upload/upload.html +41 -0
  130. package/src/fields/upload/upload.ts +137 -0
  131. package/src/interfaces/interfaces.ts +61 -0
  132. package/src/public-api.ts +38 -0
  133. package/src/util/ClassOf.pipe.ts +11 -0
  134. package/src/util/JsonColorido.pipe.ts +11 -0
  135. package/src/util/util.ts +2151 -0
  136. package/tsconfig.lib.json +16 -0
  137. package/tsconfig.lib.prod.json +9 -0
  138. package/tsconfig.spec.json +13 -0
  139. package/fesm2022/masterkeymaterial-ui.mjs +0 -6457
  140. package/fesm2022/masterkeymaterial-ui.mjs.map +0 -1
  141. package/types/masterkeymaterial-ui.d.ts +0 -928
@@ -0,0 +1,25 @@
1
+ import { Component, computed, input } from '@angular/core';
2
+ import { LibUtil } from '../../util/util';
3
+
4
+ @Component({
5
+ selector: 'ui-chip',
6
+ templateUrl: './ui-chip.html',
7
+ styleUrl: './ui-chip.css',
8
+ })
9
+ export class UiChip {
10
+
11
+ // HSL
12
+ cor = input<number | null | undefined>();
13
+
14
+ hue = computed<number | null>(() => {
15
+ let hue = this.cor();
16
+ if (LibUtil.classof(hue) == 'number') {
17
+ if (hue! < 0) { return 0; };
18
+ if (hue! > 359) { return 359; };
19
+ return hue!;
20
+ }
21
+ return null;
22
+ });
23
+
24
+
25
+ }
@@ -0,0 +1,91 @@
1
+ :host {
2
+ display: flex;
3
+ align-items: center;
4
+ justify-content: center;
5
+ flex: 1;
6
+ position: relative;
7
+ overflow: hidden;
8
+ padding: 5px;
9
+ width: 100%;
10
+ min-height: var(--ui-min-height, 200px);
11
+ }
12
+
13
+ .dropzone {
14
+ --minOffset: 1px;
15
+ padding: 2px;
16
+ display: flex;
17
+ justify-content: center;
18
+ align-items: center;
19
+ border-radius: var(--MasterRadius);
20
+ background-color: var(--sys-primary-15);
21
+ cursor: pointer;
22
+ outline: 1px dashed var(--sys-primary);
23
+ outline-offset: var(--minOffset);
24
+ position: absolute;
25
+ top: 5px;
26
+ left: 5px;
27
+ width: calc(100% - 10px);
28
+ height: calc(100% - 10px);
29
+ overflow: hidden;
30
+ z-index: 1;
31
+ }
32
+
33
+ .dropzone.naosobrepor {
34
+ z-index: 0;
35
+ }
36
+
37
+ .dropzone.disabled {
38
+ filter: grayscale(1);
39
+ cursor: auto;
40
+ pointer-events: none;
41
+ opacity: 0.8;
42
+ }
43
+
44
+ .dropzone * {
45
+ pointer-events: none;
46
+ }
47
+
48
+ .dropzone.dragging .grid {
49
+ pointer-events: none !important;
50
+ }
51
+
52
+ .dropzone.dragging {
53
+ outline: 3px dashed var(--sys-primary);
54
+ animation: onDragging 0.8s infinite ease-in-out;
55
+ }
56
+
57
+ @keyframes onDragging {
58
+ 0% {
59
+ outline-offset: var(--minOffset);
60
+ }
61
+
62
+ 50% {
63
+ outline-offset: -8px;
64
+ }
65
+
66
+ 100% {
67
+ outline-offset: var(--minOffset);
68
+ }
69
+ }
70
+
71
+
72
+ .ripple {
73
+ position: absolute;
74
+ border-radius: 50%;
75
+ background: rgba(var(--toDark), 0.2);
76
+ transform: scale(0);
77
+ animation: ripple-animation 0.7s ease-out;
78
+ pointer-events: none;
79
+ z-index: 2;
80
+ }
81
+
82
+ @keyframes ripple-animation {
83
+ to {
84
+ transform: scale(1.4);
85
+ opacity: 0;
86
+ }
87
+ }
88
+
89
+ .ripple.red {
90
+ background: rgba(255, 0, 0, 0.2);
91
+ }
@@ -0,0 +1,8 @@
1
+ <div #dropzonearea class="dropzone" [class.naosobrepor]="!sobrepor()" (dragenter)="onDropZone('dragenter',$event)"
2
+ (dragleave)="onDropZone('dragleave',$event)" (drop)="onDrop($event)" (dragover)="onDropZone('dragover',$event)"
3
+ (click)="onDropZone('click',$event)" [class.disabled]="disabled()" [class.dragging]="isDragging">
4
+ <span #rippleEffect class="rippleArea">
5
+ <span #ripple class="ripple"></span>
6
+ </span>
7
+ </div>
8
+ <ng-content></ng-content>
@@ -0,0 +1,153 @@
1
+ import { Component, ElementRef, input, model, output, viewChild } from '@angular/core';
2
+ import { IDropOutput, IDropZoneEvent, IFileMetadata } from '../../interfaces/interfaces';
3
+ import { LibUtil, LOG } from '../../util/util';
4
+
5
+ @Component({
6
+ selector: 'ui-drop-zone',
7
+ templateUrl: './ui-drop-zone.html',
8
+ styleUrl: './ui-drop-zone.css',
9
+ })
10
+ export class UiDropZone {
11
+
12
+ value = model<IDropOutput>();
13
+ disabled = input<boolean>();
14
+ sobrepor = input<boolean>();
15
+ clicked = output<Event>();
16
+ changed = output<IDropOutput>();
17
+
18
+ rippleEffect = viewChild('rippleEffect', { read: ElementRef });
19
+ ripple = viewChild('ripple', { read: ElementRef });
20
+ // dropzonearea = viewChild('dropzonearea', { read: ElementRef })
21
+ isDragging: boolean = false;
22
+
23
+ async onDropZone(tipo: IDropZoneEvent, ev: Event) {
24
+ ev.preventDefault();
25
+ ev.stopPropagation();
26
+ if (this.disabled()) return;
27
+
28
+ let target = ((ev as Event).target as HTMLDivElement);
29
+ if (tipo == "dragenter" && !this.disabled()) this.isDragging = true;
30
+ if (tipo == "dragleave" && !this.disabled()) this.isDragging = false;
31
+ if (tipo == "click" && target && target.classList?.contains("dropzone")) {
32
+ this.clicked.emit(ev);
33
+ }
34
+ }
35
+
36
+ async onDrop(ev: DragEvent) {
37
+ ev.preventDefault();
38
+ ev.stopPropagation();
39
+ this.isDragging = false;
40
+ if (this.disabled()) return;
41
+
42
+ const dataTransfer = ev.dataTransfer;
43
+ if (!dataTransfer) {
44
+ this.createRipple(ev as DragEvent, "red");
45
+ return;
46
+ }
47
+ this.createRipple(ev as DragEvent);
48
+
49
+ const output: IDropOutput = {
50
+ timestamp: new Date().toISOString(),
51
+ types: (dataTransfer.types as any),
52
+ tipo: "unknown",
53
+ };
54
+
55
+ // 1. Verificar se há arquivos
56
+ if (dataTransfer.files && dataTransfer.files.length > 0) {
57
+
58
+ output.data = ([] as IFileMetadata[]);
59
+ output.tipo = "file";
60
+
61
+ for await (let file of dataTransfer.files) {
62
+ let lastIndexOf = file.name.lastIndexOf(".");
63
+ if (lastIndexOf < 0) {
64
+ LOG(1, `❌ O arquivo ${file.name} está sem uma extensão.`);
65
+ continue;
66
+ }
67
+ let base64: string | null = await LibUtil.fileReader(file);
68
+ if (!base64) {
69
+ LOG(1, `❌ Ocorreu um erro com o arquivo ${file.name}.`);
70
+ continue;
71
+ }
72
+
73
+ (output.data as IFileMetadata[]).push({
74
+ base64: base64,
75
+ name: file.name,
76
+ size: file.size,
77
+ extension: file.name.slice(lastIndexOf), // inclui o "."
78
+ type: file.type,
79
+ lastModifiedIso: new Date(file.lastModified).toISOString(),
80
+ });
81
+ }
82
+
83
+ }
84
+
85
+ // 2. Verificar se há texto
86
+ const text = dataTransfer.getData('text/plain');
87
+ if (text) {
88
+ output.data = text;
89
+ output.tipo = "text";
90
+ }
91
+
92
+ // 3. Verificar se há HTML
93
+ const html = dataTransfer.getData('text/html');
94
+ if (html) {
95
+ output.data = html;
96
+ output.tipo = "html";
97
+ }
98
+
99
+ // 4. Verificar se há URL
100
+ const url = dataTransfer.getData('text/uri-list');
101
+ if (url) {
102
+ output.data = url;
103
+ output.tipo = "url";
104
+ }
105
+
106
+ // 5. Verificar se há dados JSON customizados
107
+ try {
108
+ const json = dataTransfer.getData('application/json');
109
+ if (json) {
110
+ output.data = JSON.parse(json);
111
+ output.tipo = "json";
112
+ }
113
+ } catch (e) {
114
+ // JSON inválido, ignorar
115
+ }
116
+
117
+ // 6. Capturar todos os outros tipos de dados disponíveis
118
+ dataTransfer.types.forEach(type => {
119
+ if (!['text/plain', 'text/html', 'text/uri-list', 'application/json', 'Files'].includes(type)) {
120
+ const data = dataTransfer.getData(type);
121
+ if (data) {
122
+ output.data = data;
123
+ output.tipo = "unknown";
124
+ }
125
+ }
126
+ });
127
+
128
+ this.value.set(output);
129
+ this.changed.emit(output);
130
+ }
131
+
132
+ createRipple(ev: DragEvent, classColor: string = "") {
133
+ const rippleEffect = ev.currentTarget ?? this.rippleEffect()?.nativeElement;
134
+ const ripple = this.ripple()?.nativeElement.cloneNode(true) as HTMLElement;
135
+ const rect = rippleEffect.getBoundingClientRect();
136
+ // Calcula a posição do clique relativa ao botão
137
+ const x = ev.clientX - rect.left;
138
+ const y = ev.clientY - rect.top;
139
+ // Define o tamanho do ripple (maior dimensão do botão * 2)
140
+ const size = Math.max(rect.width, rect.height) * 2;
141
+ ripple.style.width = ripple.style.height = size + 'px';
142
+ ripple.style.left = (x - size / 2) + 'px';
143
+ ripple.style.top = (y - size / 2) + 'px';
144
+ ripple.classList.add('ripple');
145
+ if (classColor) {
146
+ ripple.classList.add(classColor);
147
+ }
148
+ rippleEffect.appendChild(ripple);
149
+ ripple.addEventListener('animationend', () => {
150
+ ripple.remove();
151
+ });
152
+ }
153
+ }
@@ -0,0 +1,43 @@
1
+ :host {
2
+ width: 100%;
3
+ }
4
+
5
+ .e-filelist-area {
6
+ display: flex;
7
+ flex-direction: column;
8
+ gap: 12px;
9
+ margin: 6px 0;
10
+ width: 100%;
11
+ }
12
+
13
+ .e-filelist-item {
14
+ display: grid;
15
+ grid-template-columns: 1fr auto 1fr;
16
+ gap: 5px;
17
+ }
18
+
19
+ .e-filelist-item-icon {
20
+ display: flex;
21
+ flex-direction: column;
22
+ justify-content: center;
23
+ align-items: center;
24
+ height: 100%;
25
+ aspect-ratio: 1 / 1;
26
+ border-radius: 6px;
27
+ font-size: 1.2rem;
28
+ }
29
+
30
+ .e-filelist-item-icon-ext {
31
+ display: flex;
32
+ justify-content: center;
33
+ align-items: center;
34
+ font-size: 0.7rem;
35
+ }
36
+
37
+ .e-filelist-item-text {
38
+ align-items: center;
39
+ align-content: center;
40
+ overflow: hidden;
41
+ text-overflow: ellipsis;
42
+ white-space: nowrap;
43
+ }
@@ -0,0 +1,17 @@
1
+ <div class="e-filelist-area">
2
+ @for (file of filesList(); track $index) {
3
+ <div class="e-filelist-item">
4
+ <div class="e-filelist-item-icon">
5
+ <i class="bi bi-file-earmark-fill"></i>
6
+ <div class="e-filelist-item-icon-ext">{{ file.extension?.slice(1) }}</div>
7
+ </div>
8
+ <div class="e-filelist-item-text">{{ file.name }}</div>
9
+ <div class="e-filelist-action">
10
+ @if(!disabled()){
11
+ <ui-button tipo="icon" tema="error" [disabled]="disabled()" (click)="onDelete(file)" icone="bi bi-x-lg">
12
+ </ui-button>
13
+ }
14
+ </div>
15
+ </div>
16
+ }
17
+ </div>
@@ -0,0 +1,22 @@
1
+ import { Component, input, output } from '@angular/core';
2
+ import { UiButton } from "../ui-button/ui-button";
3
+ import { IFileMetadata } from '../../interfaces/interfaces';
4
+
5
+ @Component({
6
+ selector: 'ui-file-list',
7
+ templateUrl: './ui-file-list.html',
8
+ styleUrl: './ui-file-list.css',
9
+ imports: [UiButton]
10
+ })
11
+ export class UiFileList {
12
+
13
+ disabled = input<boolean>();
14
+ filesList = input<IFileMetadata[]>();
15
+ remove = output<IFileMetadata>();
16
+
17
+ onDelete(file: IFileMetadata) {
18
+ if (this.disabled()) return;
19
+ this.remove.emit(file);
20
+ }
21
+
22
+ }
@@ -0,0 +1,30 @@
1
+ :host {
2
+ display: contents;
3
+ }
4
+
5
+ .erroArea {
6
+ background-color: transparent;
7
+ border-radius: var(--MasterRadius);
8
+ font-size: 12px;
9
+ padding: 0px 8px 2px 8px;
10
+ display: flex;
11
+ flex-wrap: wrap;
12
+ justify-content: flex-end;
13
+ }
14
+
15
+ .erroArea .erroText {
16
+ color: var(--sys-error);
17
+ }
18
+
19
+ .erroArea .dicaText {
20
+ color: var(--sys-info);
21
+ }
22
+
23
+ .erroArea.hide {
24
+ display: none;
25
+ }
26
+
27
+ span {
28
+ display: block;
29
+ margin-left: 3px;
30
+ }
@@ -0,0 +1,10 @@
1
+ @if(show()){
2
+ <div class="erroArea" [class.hide]="(!errors() || errors()?.length === 0) && (!dica())">
3
+ @for (erro of errors(); track $index) {
4
+ <span class="erroText">{{ erro ?? 'Erro desconhecido' }}</span>
5
+ }
6
+ @if(dica()){
7
+ <span class="dicaText">{{ dica() ?? '' }}</span>
8
+ }
9
+ </div>
10
+ }
@@ -0,0 +1,14 @@
1
+ import { Component, input } from '@angular/core';
2
+
3
+ @Component({
4
+ selector: 'ui-list-errors',
5
+ templateUrl: './ui-list-errors.html',
6
+ styleUrl: './ui-list-errors.css',
7
+ })
8
+ export class UiListErrors {
9
+
10
+ show = input.required<boolean | undefined>();
11
+
12
+ errors = input.required<(string | undefined)[] | undefined>();
13
+ dica = input.required<string | undefined>();
14
+ }
@@ -0,0 +1,13 @@
1
+ i {
2
+ animation: spin 1s linear infinite;
3
+ }
4
+
5
+ @keyframes spin {
6
+ 0% {
7
+ transform: rotate(0deg);
8
+ }
9
+
10
+ 100% {
11
+ transform: rotate(360deg);
12
+ }
13
+ }
@@ -0,0 +1 @@
1
+ <i class="fa fa-spinner"></i>
@@ -0,0 +1,10 @@
1
+ import { Component } from '@angular/core';
2
+
3
+ @Component({
4
+ selector: 'ui-loading',
5
+ templateUrl: './ui-loading.html',
6
+ styleUrl: './ui-loading.css',
7
+ })
8
+ export class UiLoading {
9
+
10
+ }
@@ -0,0 +1,69 @@
1
+ .e-menu-area {
2
+ background-color: var(--sys-card);
3
+ border-radius: 4px;
4
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
5
+ padding: 8px 0;
6
+ display: flex;
7
+ flex-direction: column;
8
+ gap: var(--ui-gap, 4px);
9
+ user-select: none;
10
+ }
11
+
12
+ .e-menu-trigger {
13
+ flex: 1;
14
+ display: block;
15
+ }
16
+
17
+ .e-menu-overlay {
18
+ position: fixed;
19
+ top: 0;
20
+ left: 0;
21
+ width: 100%;
22
+ height: 100vh;
23
+ z-index: 1001;
24
+ background-color: transparent;
25
+ pointer-events: none;
26
+ transition: background-color 0.2s ease-in-out;
27
+ }
28
+
29
+ .e-menu-overlay.open {
30
+ background-color: rgba(0, 0, 0, 0.25);
31
+ pointer-events: auto;
32
+ }
33
+
34
+ .e-menu-container {
35
+ width: max-content;
36
+ position: fixed;
37
+ z-index: 2002;
38
+ display: flex;
39
+ flex-direction: column;
40
+ overflow: hidden;
41
+ border-radius: 10px;
42
+ transform: translateZ(0);
43
+ will-change: transform;
44
+
45
+ transform-origin: top left;
46
+ transform: scale(0.8) translate(0, -10%) rotateX(90deg) skew(15deg);
47
+
48
+ opacity: 0;
49
+ visibility: hidden;
50
+ /* transition: opacity 0.2s ease-in-out, visibility 0.2s ease-in-out, transform 0.2s ease-in-out; */
51
+ transition: all 0.15s ease-in-out;
52
+ }
53
+
54
+ .e-menu-overlay.open .e-menu-container {
55
+ color: var(--sys-on-card);
56
+ background: var(--sys-card);
57
+ outline: 1px solid var(--sys-outline);
58
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
59
+ visibility: visible;
60
+ opacity: 1;
61
+ transform: scale(1);
62
+ }
63
+
64
+ .e-menu-overlay.open .e-menu-container.smallScreen {
65
+ width: 90vw;
66
+ left: 5vw !important;
67
+ /* 170 == 300 List + 40 Search / 2 */
68
+ top: calc(50vh - 170px) !important;
69
+ }
@@ -0,0 +1,20 @@
1
+ <div #menuTrigger class="e-menu-trigger" (click)="onClickSlotBotao($event)" (keyup.Enter)="onOpenOrCloseOptions()"
2
+ (keydown.ArrowDown)="onArrowDown($event)" (keyup.ArrowUp)="onArrowUp($event)" (keyup.Escape)="closeOverlay()"
3
+ [id]="'tr'+id()" [class.open]="isOpened()">
4
+ <ng-content select="[slot='botao']">
5
+ <ui-button tipo="icon" tema="primary" [icone]="icone()"></ui-button>
6
+ </ng-content>
7
+ </div>
8
+
9
+ <div #menuOverlay class="e-menu-overlay" [class.open]="isOpened()" (click)="onClickOverlay()"
10
+ (keydown.ArrowDown)="onArrowDown($event)" (keyup.ArrowUp)="onArrowUp($event)" [style.zIndex]="zIndex()"
11
+ [id]="'ov'+id()">
12
+
13
+ <div #menuContainer class="e-menu-container" [class.smallScreen]="isSmallScreen()" [style.left]="menuPosition().left"
14
+ [style.top]="menuPosition().top" (click)="onClickContainer($event)">
15
+ <div [style.minWidth.px]="optionMinWidth()" class="e-menu-area">
16
+ <ng-content></ng-content>
17
+ </div>
18
+ </div>
19
+
20
+ </div>