@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.
- package/README.md +9 -59
- package/ng-package.json +10 -0
- package/package.json +5 -14
- package/src/elements/ui-button/ui-button.css +229 -0
- package/src/elements/ui-button/ui-button.html +12 -0
- package/src/elements/ui-button/ui-button.ts +133 -0
- package/src/elements/ui-check-box/ui-check-box.css +66 -0
- package/src/elements/ui-check-box/ui-check-box.html +5 -0
- package/src/elements/ui-check-box/ui-check-box.ts +65 -0
- package/src/elements/ui-chip/ui-chip.css +24 -0
- package/src/elements/ui-chip/ui-chip.html +3 -0
- package/src/elements/ui-chip/ui-chip.ts +25 -0
- package/src/elements/ui-drop-zone/ui-drop-zone.css +91 -0
- package/src/elements/ui-drop-zone/ui-drop-zone.html +8 -0
- package/src/elements/ui-drop-zone/ui-drop-zone.ts +153 -0
- package/src/elements/ui-file-list/ui-file-list.css +43 -0
- package/src/elements/ui-file-list/ui-file-list.html +17 -0
- package/src/elements/ui-file-list/ui-file-list.ts +22 -0
- package/src/elements/ui-list-errors/ui-list-errors.css +30 -0
- package/src/elements/ui-list-errors/ui-list-errors.html +10 -0
- package/src/elements/ui-list-errors/ui-list-errors.ts +14 -0
- package/src/elements/ui-loading/ui-loading.css +13 -0
- package/src/elements/ui-loading/ui-loading.html +1 -0
- package/src/elements/ui-loading/ui-loading.ts +10 -0
- package/src/elements/ui-menu/ui-menu.css +69 -0
- package/src/elements/ui-menu/ui-menu.html +20 -0
- package/src/elements/ui-menu/ui-menu.ts +267 -0
- package/src/elements/ui-procurar/ui-procurar.css +48 -0
- package/src/elements/ui-procurar/ui-procurar.html +14 -0
- package/src/elements/ui-procurar/ui-procurar.ts +82 -0
- package/src/elements/ui-progress/ui-progress.css +0 -0
- package/src/elements/ui-progress/ui-progress.html +1 -0
- package/src/elements/ui-progress/ui-progress.ts +15 -0
- package/src/elements/ui-select/ui-select.css +211 -0
- package/src/elements/ui-select/ui-select.html +46 -0
- package/src/elements/ui-select/ui-select.ts +482 -0
- package/src/elements/ui-slide/ui-slide.css +75 -0
- package/src/elements/ui-slide/ui-slide.html +7 -0
- package/src/elements/ui-slide/ui-slide.ts +61 -0
- package/src/fields/Base/BaseFieldsForm/BaseFieldsForm.component.ts +113 -0
- package/src/fields/Base/BaseFieldsValues/BaseFieldsValues.ts +112 -0
- package/src/fields/Formulario/Formulario.ts +1056 -0
- package/src/fields/Formulario/form-action/form-action.css +98 -0
- package/src/fields/Formulario/form-action/form-action.html +75 -0
- package/src/fields/Formulario/form-action/form-action.ts +187 -0
- package/src/fields/Formulario/form-controls/form-controls.css +108 -0
- package/src/fields/Formulario/form-controls/form-controls.html +105 -0
- package/src/fields/Formulario/form-controls/form-controls.ts +122 -0
- package/src/fields/Formulario/form-fase/form-fase.css +84 -0
- package/src/fields/Formulario/form-fase/form-fase.html +24 -0
- package/src/fields/Formulario/form-fase/form-fase.ts +157 -0
- package/src/fields/Formulario/form-filter/form-filter.css +50 -0
- package/src/fields/Formulario/form-filter/form-filter.html +25 -0
- package/src/fields/Formulario/form-filter/form-filter.ts +53 -0
- package/src/fields/Formulario/form-no-action/form-no-action.css +32 -0
- package/src/fields/Formulario/form-no-action/form-no-action.html +12 -0
- package/src/fields/Formulario/form-no-action/form-no-action.ts +21 -0
- package/src/fields/Formulario/formated-values/formated-values.css +104 -0
- package/src/fields/Formulario/formated-values/formated-values.html +15 -0
- package/src/fields/Formulario/formated-values/formated-values.ts +186 -0
- package/src/fields/Formulario/single-values/single-values.css +88 -0
- package/src/fields/Formulario/single-values/single-values.html +11 -0
- package/src/fields/Formulario/single-values/single-values.ts +65 -0
- package/src/fields/autocomplete/autocomplete.css +94 -0
- package/src/fields/autocomplete/autocomplete.html +38 -0
- package/src/fields/autocomplete/autocomplete.ts +294 -0
- package/src/fields/button/button.css +7 -0
- package/src/fields/button/button.html +19 -0
- package/src/fields/button/button.ts +38 -0
- package/src/fields/checkbox/checkbox.css +27 -0
- package/src/fields/checkbox/checkbox.html +20 -0
- package/src/fields/checkbox/checkbox.ts +44 -0
- package/src/fields/color/CirculoColorido/circulocolorido.css +50 -0
- package/src/fields/color/CirculoColorido/circulocolorido.html +8 -0
- package/src/fields/color/CirculoColorido/circulocolorido.ts +24 -0
- package/src/fields/color/color.css +15 -0
- package/src/fields/color/color.html +24 -0
- package/src/fields/color/color.ts +47 -0
- package/src/fields/date/date.html +19 -0
- package/src/fields/date/date.ts +29 -0
- package/src/fields/datetime/datetime.html +19 -0
- package/src/fields/datetime/datetime.ts +29 -0
- package/src/fields/display/display.css +7 -0
- package/src/fields/display/display.html +20 -0
- package/src/fields/display/display.ts +43 -0
- package/src/fields/editor/editor.css +51 -0
- package/src/fields/editor/editor.html +37 -0
- package/src/fields/editor/editor.ts +218 -0
- package/src/fields/email/email.html +19 -0
- package/src/fields/email/email.ts +29 -0
- package/src/fields/fields.css +180 -0
- package/src/fields/generic/generic.html +3 -0
- package/src/fields/generic/generic.ts +91 -0
- package/src/fields/hidden/hidden.html +3 -0
- package/src/fields/hidden/hidden.ts +20 -0
- package/src/fields/icon/icon.css +19 -0
- package/src/fields/icon/icon.html +27 -0
- package/src/fields/icon/icon.ts +31 -0
- package/src/fields/multifactor/multifactor.css +21 -0
- package/src/fields/multifactor/multifactor.html +39 -0
- package/src/fields/multifactor/multifactor.ts +106 -0
- package/src/fields/multikv/multikv.css +43 -0
- package/src/fields/multikv/multikv.html +47 -0
- package/src/fields/multikv/multikv.ts +88 -0
- package/src/fields/multitext/multitext.css +36 -0
- package/src/fields/multitext/multitext.html +38 -0
- package/src/fields/multitext/multitext.ts +75 -0
- package/src/fields/number/number.html +20 -0
- package/src/fields/number/number.ts +35 -0
- package/src/fields/password/password.html +23 -0
- package/src/fields/password/password.ts +37 -0
- package/src/fields/search/search.css +0 -0
- package/src/fields/search/search.html +19 -0
- package/src/fields/search/search.ts +54 -0
- package/src/fields/select/select.css +15 -0
- package/src/fields/select/select.html +18 -0
- package/src/fields/select/select.ts +52 -0
- package/src/fields/slide/slide.css +27 -0
- package/src/fields/slide/slide.html +20 -0
- package/src/fields/slide/slide.ts +45 -0
- package/src/fields/text/text.html +19 -0
- package/src/fields/text/text.ts +30 -0
- package/src/fields/textarea/textarea.css +4 -0
- package/src/fields/textarea/textarea.html +20 -0
- package/src/fields/textarea/textarea.ts +31 -0
- package/src/fields/time/time.html +19 -0
- package/src/fields/time/time.ts +29 -0
- package/src/fields/upload/upload.css +24 -0
- package/src/fields/upload/upload.html +41 -0
- package/src/fields/upload/upload.ts +137 -0
- package/src/interfaces/interfaces.ts +61 -0
- package/src/public-api.ts +38 -0
- package/src/util/ClassOf.pipe.ts +11 -0
- package/src/util/JsonColorido.pipe.ts +11 -0
- package/src/util/util.ts +2151 -0
- package/tsconfig.lib.json +16 -0
- package/tsconfig.lib.prod.json +9 -0
- package/tsconfig.spec.json +13 -0
- package/fesm2022/masterkeymaterial-ui.mjs +0 -6457
- package/fesm2022/masterkeymaterial-ui.mjs.map +0 -1
- package/types/masterkeymaterial-ui.d.ts +0 -928
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import { AfterViewInit, Component, effect, ElementRef, HostListener, inject, input, model, OnDestroy, OnInit, signal, viewChild } from '@angular/core';
|
|
2
|
+
import { autoUpdate, computePosition, flip, offset, shift } from '@floating-ui/dom';
|
|
3
|
+
import { UiButton } from "../ui-button/ui-button";
|
|
4
|
+
import { LibUtil, LOG } from '../../util/util';
|
|
5
|
+
import { IPosicoesFloating } from '../../interfaces/interfaces';
|
|
6
|
+
|
|
7
|
+
@Component({
|
|
8
|
+
selector: 'ui-menu',
|
|
9
|
+
templateUrl: './ui-menu.html',
|
|
10
|
+
styleUrl: './ui-menu.css',
|
|
11
|
+
imports: [UiButton],
|
|
12
|
+
host: { '[class.opened]': 'isOpened()' }
|
|
13
|
+
})
|
|
14
|
+
export class UiMenu implements OnDestroy, OnInit, AfterViewInit {
|
|
15
|
+
// UTILIZE:
|
|
16
|
+
// 'slot:botao' para colocar o botão que irá abrir o menu, ou utilize o botão padrão (três pontos verticais)
|
|
17
|
+
// O demais elementos dentro do <ui-menu> serão considerados opções do menu, e serão exibidos dentro do overlay quando o menu for aberto
|
|
18
|
+
|
|
19
|
+
elementRef: ElementRef = inject(ElementRef);
|
|
20
|
+
|
|
21
|
+
readonly disabled = input<boolean>();
|
|
22
|
+
readonly icone = input<string | undefined | null>("bi bi-three-dots-vertical");
|
|
23
|
+
autoCloseInCascade = model<boolean>(true);
|
|
24
|
+
|
|
25
|
+
posicao = model<IPosicoesFloating & string>('right-start');
|
|
26
|
+
isOpened = model(false);
|
|
27
|
+
id = signal(LibUtil.uuid().split('-')[0]);
|
|
28
|
+
internalId = signal<{ id: string | undefined; changed: boolean } | undefined>({ id: undefined, changed: false });
|
|
29
|
+
isSmallScreen = signal(window.innerWidth < 500);
|
|
30
|
+
optionMinWidth = signal<number>(0);
|
|
31
|
+
menuPosition = signal<{ top: string; left: string }>({ top: '0px', left: '0px' });
|
|
32
|
+
zIndex = signal<string>('999');
|
|
33
|
+
closeOverlayObserver = new MutationObserver((mutations) => {
|
|
34
|
+
let hasOpenClass = false;
|
|
35
|
+
for (const mutation of mutations) {
|
|
36
|
+
if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
|
|
37
|
+
const target = mutation.target as HTMLElement;
|
|
38
|
+
if (target.classList.contains('open')) {
|
|
39
|
+
hasOpenClass = true;
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (!hasOpenClass) {
|
|
45
|
+
// LOG(1, "%cObserver detectou overlay fechado:", 'color: lightcoral;', mutations?.[0]);
|
|
46
|
+
this.closeOverlay(true); // Callback para fechar o overlay quando a mutação indicar que perdeu a classe 'open'
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
readonly menuTrigger = viewChild<ElementRef>('menuTrigger');
|
|
52
|
+
readonly menuOverlay = viewChild<ElementRef>('menuOverlay');
|
|
53
|
+
readonly menuContainer = viewChild<ElementRef>('menuContainer');
|
|
54
|
+
|
|
55
|
+
constructor() {
|
|
56
|
+
effect(() => {
|
|
57
|
+
|
|
58
|
+
const eTrigger = this.menuTrigger()?.nativeElement as HTMLElement;
|
|
59
|
+
if (!eTrigger) return;
|
|
60
|
+
|
|
61
|
+
if (!this.isOpened()) return;
|
|
62
|
+
|
|
63
|
+
const cleanupAutoUpdate = autoUpdate(
|
|
64
|
+
eTrigger,
|
|
65
|
+
this.menuContainer()?.nativeElement,
|
|
66
|
+
() => this.updatePosition()
|
|
67
|
+
);
|
|
68
|
+
return () => {
|
|
69
|
+
cleanupAutoUpdate();
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// Atualiza posição quando o menu abre
|
|
75
|
+
effect(() => {
|
|
76
|
+
if (this.isOpened()) {
|
|
77
|
+
setTimeout(() => {
|
|
78
|
+
this.updatePosition();
|
|
79
|
+
}, 1);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
effect(() => {
|
|
83
|
+
let internalId = this.internalId();
|
|
84
|
+
if (internalId?.id === undefined && internalId?.changed === true) {
|
|
85
|
+
// LOG(1, "%cAlterado Internal:", 'color: lightcoral;', internalId, " - Menu ID:", this.id());
|
|
86
|
+
this.closeOverlay();
|
|
87
|
+
};
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
ngOnInit() {
|
|
91
|
+
// Inicializa o zIndex com base no valor armazenado no sessionStorage
|
|
92
|
+
this.zIndex.set(sessionStorage.getItem(`ui-menu-index`) ? (Number(sessionStorage.getItem(`ui-menu-index`)) + 1).toString() : '1001');
|
|
93
|
+
sessionStorage.setItem(`ui-menu-index`, this.zIndex());
|
|
94
|
+
}
|
|
95
|
+
ngOnDestroy() {
|
|
96
|
+
if (this.isOpened() == true) this.closeOverlay();
|
|
97
|
+
this.closeOverlayObserver.disconnect();
|
|
98
|
+
// this.cleanupScrollListeners();
|
|
99
|
+
}
|
|
100
|
+
ngAfterViewInit() {
|
|
101
|
+
this.checkScreenSize();
|
|
102
|
+
this.setOverlaySizeToSizeViewport();
|
|
103
|
+
|
|
104
|
+
this.updatePosition();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Abre ou fecha o overlay de opções
|
|
108
|
+
onOpenOrCloseOptions() {
|
|
109
|
+
if (!this.disabled()) {
|
|
110
|
+
if (this.isOpened()) {
|
|
111
|
+
this.closeOverlay();
|
|
112
|
+
} else {
|
|
113
|
+
this.openOverlay();
|
|
114
|
+
}
|
|
115
|
+
this.menuTrigger()?.nativeElement.focus();
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
// Abre ou fecha o overlay de opções
|
|
119
|
+
onClickSlotBotao(event: Event) {
|
|
120
|
+
if (!this.disabled()) {
|
|
121
|
+
this.openOverlay();
|
|
122
|
+
this.menuTrigger()?.nativeElement.focus();
|
|
123
|
+
}
|
|
124
|
+
// LOG(1, "%cAbriu ID:", 'color: lightgreen;', this.id());
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
onClickOverlay() {
|
|
128
|
+
// LOG(1, "%cFECHOU OVERLAY ID:", 'color: lightblue;', this.id());
|
|
129
|
+
this.closeOverlay();
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
onClickContainer(event: Event) {
|
|
134
|
+
event.stopPropagation();
|
|
135
|
+
let closestOverlay = (event.target as HTMLElement).closest('.e-menu-overlay');
|
|
136
|
+
let overlayId = closestOverlay?.id?.replaceAll('ov', '');
|
|
137
|
+
let closestTrigger = (event.target as HTMLElement).closest('.e-menu-trigger');
|
|
138
|
+
let triggerId = closestTrigger?.id?.replaceAll('tr', '');
|
|
139
|
+
this.internalId.set({ id: triggerId, changed: true });
|
|
140
|
+
|
|
141
|
+
// LOG(1, 'Triger ID:', triggerId, ' - Overlay ID:', overlayId);
|
|
142
|
+
|
|
143
|
+
if (overlayId == this.id() && triggerId != null && triggerId != this.id()) {
|
|
144
|
+
// Um menu interno foi clicado, não fecha o overlay
|
|
145
|
+
// O atual nível de menu irá observar o elemento closestTrigger e só irá fechar o overlay quando o elemento trigger fechar.
|
|
146
|
+
this.closeOverlayObserver.observe(closestTrigger as HTMLElement, { attributes: true, attributeFilter: ['class'] });
|
|
147
|
+
} else {
|
|
148
|
+
// Clicou no container, fecha o overlay
|
|
149
|
+
this.closeOverlay();
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Fecha o overlay de opções
|
|
155
|
+
protected closeOverlay(fromCascade: boolean = false) {
|
|
156
|
+
if (fromCascade && !this.autoCloseInCascade()) return;
|
|
157
|
+
|
|
158
|
+
this.closeOverlayObserver.disconnect();
|
|
159
|
+
setTimeout(() => {
|
|
160
|
+
this.isOpened.set(false);
|
|
161
|
+
}, 2)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Abre o overlay de opções
|
|
165
|
+
protected openOverlay() {
|
|
166
|
+
this.updatePosition();
|
|
167
|
+
setTimeout(() => {
|
|
168
|
+
this.isOpened.set(true);
|
|
169
|
+
}, 2)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Atualiza a posição do menu de opções
|
|
173
|
+
private async updatePosition() {
|
|
174
|
+
if (this.isSmallScreen()) return;
|
|
175
|
+
|
|
176
|
+
const trigger = this.menuTrigger()?.nativeElement;
|
|
177
|
+
const menuContainer = this.menuContainer()?.nativeElement;
|
|
178
|
+
if (!trigger || !menuContainer) return;
|
|
179
|
+
|
|
180
|
+
const { x, y } = await computePosition(trigger, menuContainer, {
|
|
181
|
+
placement: this.posicao(),
|
|
182
|
+
middleware: [
|
|
183
|
+
offset(2),
|
|
184
|
+
flip({
|
|
185
|
+
fallbackPlacements: ['left-start', 'bottom-start', 'top-start', 'bottom-end', 'top-end'],
|
|
186
|
+
}),
|
|
187
|
+
shift({ padding: 10 }),
|
|
188
|
+
],
|
|
189
|
+
});
|
|
190
|
+
this.menuPosition.set({
|
|
191
|
+
left: `${x}px`,
|
|
192
|
+
top: `${y}px`
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
setOverlaySizeToSizeViewport() {
|
|
197
|
+
// if (!this.isOpened()) return;
|
|
198
|
+
|
|
199
|
+
// Obtem o tamanho da largura da viewport
|
|
200
|
+
const viewportWidth = window.innerWidth;
|
|
201
|
+
const parcialViewport = viewportWidth * 0.92;
|
|
202
|
+
|
|
203
|
+
const overlay = this.menuOverlay()?.nativeElement as HTMLElement;
|
|
204
|
+
if (overlay) {
|
|
205
|
+
let currentElement = overlay.parentElement as HTMLElement | null;
|
|
206
|
+
while (currentElement) {
|
|
207
|
+
let larguraOverlay = overlay.clientWidth;
|
|
208
|
+
|
|
209
|
+
// Se chegar no body, para (para evitar mover o overlay para fora do body)
|
|
210
|
+
if (currentElement.tagName.toLowerCase() === "body") break;
|
|
211
|
+
|
|
212
|
+
// Move o overlay para o próximo nível acima
|
|
213
|
+
currentElement.appendChild(overlay);
|
|
214
|
+
|
|
215
|
+
if (larguraOverlay >= parcialViewport) {
|
|
216
|
+
currentElement = null;
|
|
217
|
+
break;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
currentElement = currentElement.parentElement as HTMLElement;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
onChangeMediaQuery(e: MediaQueryListEvent | MediaQueryList) {
|
|
227
|
+
this.isSmallScreen.set(e.matches);
|
|
228
|
+
const eTrigger = this.menuTrigger()?.nativeElement as HTMLElement;
|
|
229
|
+
if (eTrigger) {
|
|
230
|
+
if (this.isSmallScreen()) {
|
|
231
|
+
this.optionMinWidth.set(0);
|
|
232
|
+
} else {
|
|
233
|
+
this.optionMinWidth.set(eTrigger.offsetWidth - 4);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
checkScreenSize() {
|
|
239
|
+
const mediaQuery = window.matchMedia('(max-width: 500px)');
|
|
240
|
+
this.onChangeMediaQuery(mediaQuery);
|
|
241
|
+
mediaQuery.addEventListener('change', this.onChangeMediaQuery.bind(this));
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
onArrowUp(event: Event) {
|
|
245
|
+
event.preventDefault();
|
|
246
|
+
// this.moveFocoPara('cima', event);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
onArrowDown(event: Event) {
|
|
250
|
+
event.preventDefault();
|
|
251
|
+
// this.moveFocoPara('baixo', event);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// moveFocoPara(direcao: 'cima' | 'baixo', event: Event) {
|
|
255
|
+
// this.openOverlay();
|
|
256
|
+
// LOG(1, `Moverá para ${direcao} - Event:`, event);
|
|
257
|
+
// const container = this.menuContainer()?.nativeElement as HTMLElement;
|
|
258
|
+
// if (!container) return;
|
|
259
|
+
|
|
260
|
+
// const focusableElements = Array.from(container.querySelectorAll('.e-menu-area>*')).filter(el => el instanceof HTMLElement && !el.hasAttribute('disabled')) as HTMLElement[];
|
|
261
|
+
// if (focusableElements.length === 0) return;
|
|
262
|
+
|
|
263
|
+
// //
|
|
264
|
+
|
|
265
|
+
// }
|
|
266
|
+
|
|
267
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
:host {
|
|
2
|
+
display: flex;
|
|
3
|
+
align-items: center;
|
|
4
|
+
width: 100%;
|
|
5
|
+
height: 100%;
|
|
6
|
+
padding: 0px;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.e-procurar-input-container {
|
|
10
|
+
width: 200px;
|
|
11
|
+
display: flex;
|
|
12
|
+
align-items: center;
|
|
13
|
+
justify-content: center;
|
|
14
|
+
transition: width 1s cubic-bezier(0.075, 0.82, 0.165, 1);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.e-procurar-input-container.colapsed {
|
|
18
|
+
width: 1px;
|
|
19
|
+
padding: 0px;
|
|
20
|
+
transition: width 1s cubic-bezier(0.075, 0.82, 0.165, 1);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.e-procurar-input {
|
|
24
|
+
width: 100%;
|
|
25
|
+
height: auto;
|
|
26
|
+
cursor: text;
|
|
27
|
+
border: none;
|
|
28
|
+
outline: none;
|
|
29
|
+
background: transparent;
|
|
30
|
+
caret-color: var(--sys-primary);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.e-procurar-icone-search {
|
|
34
|
+
color: color-mix(in srgb, var(--sys-primary) 60%, var(--sys-background) 40%);
|
|
35
|
+
--ui-font-size: 14px;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.e-procurar-botao-clear {
|
|
39
|
+
color: color-mix(in srgb, var(--sys-primary) 80%, var(--sys-background) 20%);
|
|
40
|
+
margin-left: 7px;
|
|
41
|
+
--ui-font-size: 14px;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.e-procurar-input-container.colapsed .e-procurar-icone-search,
|
|
45
|
+
.e-procurar-input-container.colapsed .e-procurar-botao-clear {
|
|
46
|
+
margin-left: 0px;
|
|
47
|
+
--ui-font-size: 12px;
|
|
48
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<ui-button tipo="icon" tema="primary" class="e-procurar-icone-search" (clicked)="onClickSearchIcon()" tabindex="-1"
|
|
2
|
+
icone="fa fa-search">
|
|
3
|
+
</ui-button>
|
|
4
|
+
<div class="e-procurar-input-container" [class.colapsed]="computedColapsed()">
|
|
5
|
+
<input #searchInput type="text" class="e-procurar-input" [value]="value()" (input)="onInput($event.target.value)"
|
|
6
|
+
[name]="'procurar_'+(name() ?? '')" (change)="onChange()" [placeholder]="placeholder() ?? 'Procurar...'"
|
|
7
|
+
[disabled]="disabled()" (keyup.Enter)="onSearch()" (keyup.Escape)="onClearSearch()" (focus)="onFocus($event)"
|
|
8
|
+
(blur)="onBlur($event)" />
|
|
9
|
+
</div>
|
|
10
|
+
@if(value().length > 0) {
|
|
11
|
+
<ui-button tipo="icon" tema="error" class="e-procurar-botao-clear" (clicked)="onClearSearch()" title="Limpar"
|
|
12
|
+
icone="fa fa-times">
|
|
13
|
+
</ui-button>
|
|
14
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { Component, computed, ElementRef, input, model, output, signal, viewChild } from '@angular/core';
|
|
2
|
+
import { UiButton } from "../ui-button/ui-button";
|
|
3
|
+
|
|
4
|
+
@Component({
|
|
5
|
+
selector: 'ui-procurar',
|
|
6
|
+
templateUrl: './ui-procurar.html',
|
|
7
|
+
styleUrl: './ui-procurar.css',
|
|
8
|
+
host: { '[class.focused]': 'focused()' },
|
|
9
|
+
imports: [UiButton],
|
|
10
|
+
})
|
|
11
|
+
export class UiProcurar {
|
|
12
|
+
|
|
13
|
+
readonly searchInput = viewChild<ElementRef>('searchInput');
|
|
14
|
+
|
|
15
|
+
inputed = output<string>();
|
|
16
|
+
changed = output<string>();
|
|
17
|
+
value = model<string>('');
|
|
18
|
+
colapsed = model<boolean | undefined>(false);
|
|
19
|
+
autoColapse = model<boolean | undefined>(false);
|
|
20
|
+
|
|
21
|
+
computedColapsed = computed(() => {
|
|
22
|
+
if (this.focused() || this.value().length > 0) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
if (this.autoColapse()) {
|
|
26
|
+
return this.value().length === 0;
|
|
27
|
+
}
|
|
28
|
+
return this.colapsed() ?? false;
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
name = input<string | number | undefined>();
|
|
32
|
+
placeholder = input<string>();
|
|
33
|
+
disabled = input<boolean>();
|
|
34
|
+
|
|
35
|
+
focused = signal<boolean | undefined>(false);
|
|
36
|
+
|
|
37
|
+
onInput(value: string) {
|
|
38
|
+
this.value.set(value);
|
|
39
|
+
this.inputed.emit(value);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Limpa o filtro de opções
|
|
43
|
+
onClearSearch() {
|
|
44
|
+
this.value.set('');
|
|
45
|
+
this.focusSearchInput();
|
|
46
|
+
this.onInputed();
|
|
47
|
+
this.onChange();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
focusSearchInput() {
|
|
51
|
+
this.searchInput()?.nativeElement?.focus();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
onClickSearchIcon() {
|
|
55
|
+
this.focusSearchInput();
|
|
56
|
+
this.onInputed();
|
|
57
|
+
this.onChange();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
onSearch() {
|
|
61
|
+
this.onInputed();
|
|
62
|
+
this.onChange();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
onInputed() {
|
|
66
|
+
this.inputed.emit(this.value());
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
onChange() {
|
|
70
|
+
this.changed.emit(this.value());
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
onFocus(ev: FocusEvent) {
|
|
75
|
+
this.focused.set(true);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
onBlur(ev: FocusEvent) {
|
|
79
|
+
this.focused.set(false);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<progress [value]="value()"></progress>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Component, input } from '@angular/core';
|
|
2
|
+
import { UiProgressMode } from '../../interfaces/interfaces';
|
|
3
|
+
|
|
4
|
+
@Component({
|
|
5
|
+
selector: 'ui-progress',
|
|
6
|
+
templateUrl: './ui-progress.html',
|
|
7
|
+
styleUrl: './ui-progress.css',
|
|
8
|
+
})
|
|
9
|
+
export class UiProgress {
|
|
10
|
+
|
|
11
|
+
value = input<number>(0);
|
|
12
|
+
bufferValue = input<number>(0);
|
|
13
|
+
mode = input<UiProgressMode>('determinate');
|
|
14
|
+
|
|
15
|
+
}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/* triggerElement */
|
|
2
|
+
.e-select-container {
|
|
3
|
+
position: relative;
|
|
4
|
+
display: flex;
|
|
5
|
+
flex: 1;
|
|
6
|
+
align-items: center;
|
|
7
|
+
justify-content: space-between;
|
|
8
|
+
padding: var(--ui-padding, none);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.e-select-container,
|
|
12
|
+
.e-select-arrow-area,
|
|
13
|
+
.e-select,
|
|
14
|
+
.e-select input {
|
|
15
|
+
cursor: pointer;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.e-select {
|
|
19
|
+
flex: 1;
|
|
20
|
+
height: var(--ui-height, auto);
|
|
21
|
+
width: var(--ui-width, auto);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.e-select input {
|
|
25
|
+
border: none;
|
|
26
|
+
background: transparent;
|
|
27
|
+
caret-color: var(--sys-primary);
|
|
28
|
+
outline: none;
|
|
29
|
+
width: 100%;
|
|
30
|
+
height: 100%;
|
|
31
|
+
display: flex;
|
|
32
|
+
justify-content: flex-start;
|
|
33
|
+
align-items: center;
|
|
34
|
+
text-align: left;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
.e-select-arrow-area {
|
|
39
|
+
display: flex;
|
|
40
|
+
align-items: center;
|
|
41
|
+
justify-content: center;
|
|
42
|
+
width: 30px;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.e-select-arrow {
|
|
46
|
+
width: 0;
|
|
47
|
+
height: 0;
|
|
48
|
+
border-left: 6px solid transparent;
|
|
49
|
+
border-right: 6px solid transparent;
|
|
50
|
+
border-top: 6px solid var(--sys-primary);
|
|
51
|
+
margin: 0 5px;
|
|
52
|
+
transition: transform 0.2s ease-in-out;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.e-select-arrow.open {
|
|
56
|
+
transform: rotate(180deg);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.e-select-overlay {
|
|
60
|
+
position: fixed;
|
|
61
|
+
top: 0;
|
|
62
|
+
left: 0;
|
|
63
|
+
width: 100%;
|
|
64
|
+
height: 100vh;
|
|
65
|
+
z-index: 2001;
|
|
66
|
+
background-color: transparent;
|
|
67
|
+
pointer-events: none;
|
|
68
|
+
transition: background-color 0.2s ease-in-out;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.e-select-overlay.open {
|
|
72
|
+
background-color: rgba(0, 0, 0, 0.25);
|
|
73
|
+
pointer-events: auto;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.e-select-options-container {
|
|
77
|
+
width: max-content;
|
|
78
|
+
position: fixed;
|
|
79
|
+
z-index: 2002;
|
|
80
|
+
display: flex;
|
|
81
|
+
flex-direction: column;
|
|
82
|
+
overflow: hidden;
|
|
83
|
+
border-radius: 10px;
|
|
84
|
+
transform: translateZ(0);
|
|
85
|
+
will-change: transform;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.e-select-options-container.open {
|
|
89
|
+
color: var(--sys-on-background);
|
|
90
|
+
background: var(--sys-background);
|
|
91
|
+
outline: 1px solid var(--sys-outline);
|
|
92
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.e-select-options-container.open.smallScreen {
|
|
96
|
+
width: 90vw;
|
|
97
|
+
left: 5vw !important;
|
|
98
|
+
/* 170 == 300 List + 40 Search / 2 */
|
|
99
|
+
top: calc(50vh - 170px) !important;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.e-select-search-area {
|
|
103
|
+
display: flex;
|
|
104
|
+
background-color: var(--sys-background);
|
|
105
|
+
border: 0;
|
|
106
|
+
border-bottom: 1px inset var(--sys-outline);
|
|
107
|
+
border-radius: 10px;
|
|
108
|
+
height: 40px;
|
|
109
|
+
max-height: 40px;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.e-select-search {
|
|
113
|
+
flex: 1;
|
|
114
|
+
width: 100%;
|
|
115
|
+
border: none;
|
|
116
|
+
background: var(--sys-surface-container-low);
|
|
117
|
+
color: var(--sys-on-surface);
|
|
118
|
+
caret-color: var(--sys-primary);
|
|
119
|
+
padding: 8px 12px 8px 4px;
|
|
120
|
+
outline: none;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.e-select-search-clearicon {
|
|
124
|
+
color: color-mix(in srgb, var(--sys-primary) 80%, var(--sys-background) 20%);
|
|
125
|
+
font-size: 1rem;
|
|
126
|
+
display: flex;
|
|
127
|
+
align-items: center;
|
|
128
|
+
justify-content: center;
|
|
129
|
+
cursor: pointer;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.e-select-search-icon {
|
|
133
|
+
color: color-mix(in srgb, var(--sys-primary) 60%, var(--sys-background) 40%);
|
|
134
|
+
font-size: 0.8rem;
|
|
135
|
+
display: flex;
|
|
136
|
+
align-items: center;
|
|
137
|
+
justify-content: center;
|
|
138
|
+
cursor: pointer;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.e-select-options-list {
|
|
142
|
+
padding: 0;
|
|
143
|
+
max-height: 300px;
|
|
144
|
+
overflow-y: auto;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.e-select-option {
|
|
148
|
+
display: flex;
|
|
149
|
+
align-items: center;
|
|
150
|
+
justify-content: space-between;
|
|
151
|
+
padding: 15px 0px;
|
|
152
|
+
margin-top: 2px;
|
|
153
|
+
cursor: pointer;
|
|
154
|
+
transition: background-color 0.2s;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.e-select-option.selected {
|
|
158
|
+
background: color-mix(in srgb, var(--sys-primary) 50%, var(--sys-background) 50%);
|
|
159
|
+
color: var(--sys-on-background);
|
|
160
|
+
font-weight: 500;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.e-select-option.choosing {
|
|
164
|
+
outline: none;
|
|
165
|
+
background: color-mix(in srgb, var(--sys-primary) 20%, var(--sys-background) 80%);
|
|
166
|
+
color: var(--sys-on-background);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.e-select-option.empty {
|
|
170
|
+
cursor: default;
|
|
171
|
+
color: var(--sys-on-surface-variant);
|
|
172
|
+
justify-content: center;
|
|
173
|
+
font-style: italic;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.e-select-option:hover {
|
|
177
|
+
background: color-mix(in srgb, var(--sys-primary) 20%, var(--sys-background) 80%);
|
|
178
|
+
color: var(--sys-on-background);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.e-select-option-text {
|
|
182
|
+
flex: 1;
|
|
183
|
+
overflow: hidden;
|
|
184
|
+
text-overflow: ellipsis;
|
|
185
|
+
white-space: nowrap;
|
|
186
|
+
user-select: none;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
.e-select-option-check {
|
|
190
|
+
width: 16px;
|
|
191
|
+
height: 16px;
|
|
192
|
+
margin: auto 5px;
|
|
193
|
+
flex-shrink: 0;
|
|
194
|
+
visibility: hidden;
|
|
195
|
+
|
|
196
|
+
/* SVG como máscara */
|
|
197
|
+
-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E");
|
|
198
|
+
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E");
|
|
199
|
+
|
|
200
|
+
-webkit-mask-size: contain;
|
|
201
|
+
mask-size: contain;
|
|
202
|
+
-webkit-mask-repeat: no-repeat;
|
|
203
|
+
mask-repeat: no-repeat;
|
|
204
|
+
-webkit-mask-position: center;
|
|
205
|
+
mask-position: center;
|
|
206
|
+
background-color: var(--sys-on-background);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
.e-select-option.selected .e-select-option-check {
|
|
210
|
+
visibility: visible;
|
|
211
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<div #triggerElement class="e-select-container" (click)="onOpenOrCloseOptions()" (keyup.Enter)="onOpenOrCloseOptions()"
|
|
2
|
+
(keyup.ArrowDown)="onOpenOrCloseOptions()" (keyup.ArrowUp)="onOpenOrCloseOptions()">
|
|
3
|
+
<div class="e-select">
|
|
4
|
+
<input #displayText type="text" [name]="'select_'+(name() ?? '')" [value]="textoExibindo()" readonly
|
|
5
|
+
[placeholder]="placeholder() ?? ''" [disabled]="disabled()" [class.outlined]="true" [class.input]="true" />
|
|
6
|
+
</div>
|
|
7
|
+
<div class="e-select-arrow-area">
|
|
8
|
+
<div class="e-select-arrow" [class.open]="isOpenedOptions()"></div>
|
|
9
|
+
</div>
|
|
10
|
+
</div>
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
<div #optionsOverlay class="e-select-overlay" [class.open]="isOpenedOptions()" (click)="closeOverlay()">
|
|
14
|
+
|
|
15
|
+
<div #optionsContainer class="e-select-options-container" [class.open]="isOpenedOptions()"
|
|
16
|
+
[class.smallScreen]="isSmallScreen()" [style.left]="menuPosition().left" [style.top]="menuPosition().top">
|
|
17
|
+
@if(isOpenedOptions()) {
|
|
18
|
+
<div class="e-select-search-area" [style.minWidth.px]="optionMinWidth()">
|
|
19
|
+
<input #optionSearchInput type="text" name="e-select-search-input" class="e-select-search"
|
|
20
|
+
(keyup)="markKey($event)" placeholder="Procurar..." [value]="textoFiltrado()" (keydown.Escape)="closeOverlay()"
|
|
21
|
+
size="8" (keydown.Tab)="closeOverlay()" (input)="onInputSearch($event.target.value)" />
|
|
22
|
+
@if(textoFiltrado().length > 0) {
|
|
23
|
+
<ui-button tipo="icon" tema="error" class="e-select-search-clearicon" (click)="onClearSearch()"
|
|
24
|
+
icone="fa fa-times"></ui-button>
|
|
25
|
+
}
|
|
26
|
+
<ui-button tipo="icon" tema="primary" class="e-select-search-icon" (click)="focusToSearchInput()"
|
|
27
|
+
icone="fa fa-search"></ui-button>
|
|
28
|
+
</div>
|
|
29
|
+
<div class="e-select-options-list">
|
|
30
|
+
@for(option of optionsFiltered(); track $index) {
|
|
31
|
+
<div class="e-select-option" [class.selected]="option.selected" [style.minWidth.px]="optionMinWidth()"
|
|
32
|
+
[title]="option.v" (click)="onSelectOption(option)" (keyup.Enter)="onSelectOption(option)" tabindex="-1"
|
|
33
|
+
[class.choosing]="option.choosing">
|
|
34
|
+
<div class="e-select-option-check"></div>
|
|
35
|
+
<div class="e-select-option-text" [innerHTML]="option.html"></div>
|
|
36
|
+
</div>
|
|
37
|
+
}@empty {
|
|
38
|
+
<div class="e-select-option empty">
|
|
39
|
+
Nenhuma opção disponível
|
|
40
|
+
</div>
|
|
41
|
+
}
|
|
42
|
+
</div>
|
|
43
|
+
}
|
|
44
|
+
</div>
|
|
45
|
+
|
|
46
|
+
</div>
|