@neural-ui/core 1.2.0 → 1.3.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.
- package/README.md +56 -88
- package/accordion/package.json +4 -0
- package/alert/package.json +4 -0
- package/autocomplete/package.json +4 -0
- package/avatar/package.json +4 -0
- package/badge/package.json +4 -0
- package/block-ui/package.json +4 -0
- package/breadcrumb/package.json +4 -0
- package/button/package.json +4 -0
- package/card/package.json +4 -0
- package/chart/package.json +4 -0
- package/checkbox/package.json +4 -0
- package/chip/package.json +4 -0
- package/code-block/package.json +4 -0
- package/color-picker/package.json +4 -0
- package/command-palette/package.json +4 -0
- package/confirm-dialog/package.json +4 -0
- package/context-menu/package.json +4 -0
- package/dashboard-grid/package.json +4 -0
- package/date-input/package.json +4 -0
- package/divider/package.json +4 -0
- package/empty-state/package.json +4 -0
- package/fesm2022/neural-ui-core-accordion.mjs +162 -0
- package/fesm2022/neural-ui-core-accordion.mjs.map +1 -0
- package/fesm2022/neural-ui-core-alert.mjs +116 -0
- package/fesm2022/neural-ui-core-alert.mjs.map +1 -0
- package/fesm2022/neural-ui-core-autocomplete.mjs +332 -0
- package/fesm2022/neural-ui-core-autocomplete.mjs.map +1 -0
- package/fesm2022/neural-ui-core-avatar.mjs +109 -0
- package/fesm2022/neural-ui-core-avatar.mjs.map +1 -0
- package/fesm2022/neural-ui-core-badge.mjs +54 -0
- package/fesm2022/neural-ui-core-badge.mjs.map +1 -0
- package/fesm2022/neural-ui-core-block-ui.mjs +95 -0
- package/fesm2022/neural-ui-core-block-ui.mjs.map +1 -0
- package/fesm2022/neural-ui-core-breadcrumb.mjs +84 -0
- package/fesm2022/neural-ui-core-breadcrumb.mjs.map +1 -0
- package/fesm2022/neural-ui-core-button.mjs +125 -0
- package/fesm2022/neural-ui-core-button.mjs.map +1 -0
- package/fesm2022/neural-ui-core-card.mjs +69 -0
- package/fesm2022/neural-ui-core-card.mjs.map +1 -0
- package/fesm2022/neural-ui-core-chart.mjs +287 -0
- package/fesm2022/neural-ui-core-chart.mjs.map +1 -0
- package/fesm2022/neural-ui-core-checkbox.mjs +138 -0
- package/fesm2022/neural-ui-core-checkbox.mjs.map +1 -0
- package/fesm2022/neural-ui-core-chip.mjs +130 -0
- package/fesm2022/neural-ui-core-chip.mjs.map +1 -0
- package/fesm2022/neural-ui-core-code-block.mjs +250 -0
- package/fesm2022/neural-ui-core-code-block.mjs.map +1 -0
- package/fesm2022/neural-ui-core-color-picker.mjs +435 -0
- package/fesm2022/neural-ui-core-color-picker.mjs.map +1 -0
- package/fesm2022/neural-ui-core-command-palette.mjs +235 -0
- package/fesm2022/neural-ui-core-command-palette.mjs.map +1 -0
- package/fesm2022/neural-ui-core-confirm-dialog.mjs +118 -0
- package/fesm2022/neural-ui-core-confirm-dialog.mjs.map +1 -0
- package/fesm2022/neural-ui-core-context-menu.mjs +158 -0
- package/fesm2022/neural-ui-core-context-menu.mjs.map +1 -0
- package/fesm2022/neural-ui-core-dashboard-grid.mjs +144 -0
- package/fesm2022/neural-ui-core-dashboard-grid.mjs.map +1 -0
- package/fesm2022/neural-ui-core-date-input.mjs +1332 -0
- package/fesm2022/neural-ui-core-date-input.mjs.map +1 -0
- package/fesm2022/neural-ui-core-divider.mjs +54 -0
- package/fesm2022/neural-ui-core-divider.mjs.map +1 -0
- package/fesm2022/neural-ui-core-empty-state.mjs +84 -0
- package/fesm2022/neural-ui-core-empty-state.mjs.map +1 -0
- package/fesm2022/neural-ui-core-filter-bar.mjs +118 -0
- package/fesm2022/neural-ui-core-filter-bar.mjs.map +1 -0
- package/fesm2022/neural-ui-core-icon.mjs +50 -0
- package/fesm2022/neural-ui-core-icon.mjs.map +1 -0
- package/fesm2022/neural-ui-core-image-viewer.mjs +309 -0
- package/fesm2022/neural-ui-core-image-viewer.mjs.map +1 -0
- package/fesm2022/neural-ui-core-input-otp.mjs +192 -0
- package/fesm2022/neural-ui-core-input-otp.mjs.map +1 -0
- package/fesm2022/neural-ui-core-input.mjs +320 -0
- package/fesm2022/neural-ui-core-input.mjs.map +1 -0
- package/fesm2022/neural-ui-core-knob.mjs +323 -0
- package/fesm2022/neural-ui-core-knob.mjs.map +1 -0
- package/fesm2022/neural-ui-core-meter-group.mjs +122 -0
- package/fesm2022/neural-ui-core-meter-group.mjs.map +1 -0
- package/fesm2022/neural-ui-core-modal.mjs +156 -0
- package/fesm2022/neural-ui-core-modal.mjs.map +1 -0
- package/fesm2022/neural-ui-core-multiselect.mjs +748 -0
- package/fesm2022/neural-ui-core-multiselect.mjs.map +1 -0
- package/fesm2022/neural-ui-core-nav.mjs +952 -0
- package/fesm2022/neural-ui-core-nav.mjs.map +1 -0
- package/fesm2022/neural-ui-core-notification-center.mjs +264 -0
- package/fesm2022/neural-ui-core-notification-center.mjs.map +1 -0
- package/fesm2022/neural-ui-core-number-input.mjs +331 -0
- package/fesm2022/neural-ui-core-number-input.mjs.map +1 -0
- package/fesm2022/neural-ui-core-pagination.mjs +198 -0
- package/fesm2022/neural-ui-core-pagination.mjs.map +1 -0
- package/fesm2022/neural-ui-core-popover.mjs +207 -0
- package/fesm2022/neural-ui-core-popover.mjs.map +1 -0
- package/fesm2022/neural-ui-core-progress-bar.mjs +105 -0
- package/fesm2022/neural-ui-core-progress-bar.mjs.map +1 -0
- package/fesm2022/neural-ui-core-radio.mjs +171 -0
- package/fesm2022/neural-ui-core-radio.mjs.map +1 -0
- package/fesm2022/neural-ui-core-rating.mjs +151 -0
- package/fesm2022/neural-ui-core-rating.mjs.map +1 -0
- package/fesm2022/neural-ui-core-select.mjs +638 -0
- package/fesm2022/neural-ui-core-select.mjs.map +1 -0
- package/fesm2022/neural-ui-core-sidebar.mjs +214 -0
- package/fesm2022/neural-ui-core-sidebar.mjs.map +1 -0
- package/fesm2022/neural-ui-core-skeleton.mjs +40 -0
- package/fesm2022/neural-ui-core-skeleton.mjs.map +1 -0
- package/fesm2022/neural-ui-core-slider.mjs +146 -0
- package/fesm2022/neural-ui-core-slider.mjs.map +1 -0
- package/fesm2022/neural-ui-core-spinner.mjs +113 -0
- package/fesm2022/neural-ui-core-spinner.mjs.map +1 -0
- package/fesm2022/neural-ui-core-split-button.mjs +252 -0
- package/fesm2022/neural-ui-core-split-button.mjs.map +1 -0
- package/fesm2022/neural-ui-core-splitter.mjs +174 -0
- package/fesm2022/neural-ui-core-splitter.mjs.map +1 -0
- package/fesm2022/neural-ui-core-stats-card.mjs +163 -0
- package/fesm2022/neural-ui-core-stats-card.mjs.map +1 -0
- package/fesm2022/neural-ui-core-stepper.mjs +204 -0
- package/fesm2022/neural-ui-core-stepper.mjs.map +1 -0
- package/fesm2022/neural-ui-core-switch.mjs +111 -0
- package/fesm2022/neural-ui-core-switch.mjs.map +1 -0
- package/fesm2022/neural-ui-core-table.mjs +1860 -0
- package/fesm2022/neural-ui-core-table.mjs.map +1 -0
- package/fesm2022/neural-ui-core-tabs.mjs +246 -0
- package/fesm2022/neural-ui-core-tabs.mjs.map +1 -0
- package/fesm2022/neural-ui-core-textarea.mjs +188 -0
- package/fesm2022/neural-ui-core-textarea.mjs.map +1 -0
- package/fesm2022/neural-ui-core-timeline.mjs +117 -0
- package/fesm2022/neural-ui-core-timeline.mjs.map +1 -0
- package/fesm2022/neural-ui-core-toast.mjs +171 -0
- package/fesm2022/neural-ui-core-toast.mjs.map +1 -0
- package/fesm2022/neural-ui-core-toggle-button-group.mjs +162 -0
- package/fesm2022/neural-ui-core-toggle-button-group.mjs.map +1 -0
- package/fesm2022/neural-ui-core-toolbar.mjs +67 -0
- package/fesm2022/neural-ui-core-toolbar.mjs.map +1 -0
- package/fesm2022/neural-ui-core-tooltip.mjs +151 -0
- package/fesm2022/neural-ui-core-tooltip.mjs.map +1 -0
- package/fesm2022/neural-ui-core-url-state.mjs +96 -0
- package/fesm2022/neural-ui-core-url-state.mjs.map +1 -0
- package/fesm2022/neural-ui-core-virtual-list.mjs +126 -0
- package/fesm2022/neural-ui-core-virtual-list.mjs.map +1 -0
- package/fesm2022/neural-ui-core.mjs +11 -8544
- package/fesm2022/neural-ui-core.mjs.map +1 -1
- package/filter-bar/package.json +4 -0
- package/icon/package.json +4 -0
- package/image-viewer/package.json +4 -0
- package/input/package.json +4 -0
- package/input-otp/package.json +4 -0
- package/knob/package.json +4 -0
- package/meter-group/package.json +4 -0
- package/modal/package.json +4 -0
- package/multiselect/package.json +4 -0
- package/nav/package.json +4 -0
- package/notification-center/package.json +4 -0
- package/number-input/package.json +4 -0
- package/package.json +252 -5
- package/pagination/package.json +4 -0
- package/popover/package.json +4 -0
- package/progress-bar/package.json +4 -0
- package/radio/package.json +4 -0
- package/rating/package.json +4 -0
- package/select/package.json +4 -0
- package/sidebar/package.json +4 -0
- package/skeleton/package.json +4 -0
- package/slider/package.json +4 -0
- package/spinner/package.json +4 -0
- package/split-button/package.json +4 -0
- package/splitter/package.json +4 -0
- package/stats-card/package.json +4 -0
- package/stepper/package.json +4 -0
- package/styles/_tokens.scss +209 -7
- package/styles.scss +1 -0
- package/switch/package.json +4 -0
- package/table/package.json +4 -0
- package/tabs/package.json +4 -0
- package/textarea/package.json +4 -0
- package/timeline/package.json +4 -0
- package/toast/package.json +4 -0
- package/toggle-button-group/package.json +4 -0
- package/toolbar/package.json +4 -0
- package/tooltip/package.json +4 -0
- package/types/neural-ui-core-accordion.d.ts +55 -0
- package/types/neural-ui-core-alert.d.ts +47 -0
- package/types/neural-ui-core-autocomplete.d.ts +69 -0
- package/types/neural-ui-core-avatar.d.ts +39 -0
- package/types/neural-ui-core-badge.d.ts +36 -0
- package/types/neural-ui-core-block-ui.d.ts +46 -0
- package/types/neural-ui-core-breadcrumb.d.ts +38 -0
- package/types/neural-ui-core-button.d.ts +55 -0
- package/types/neural-ui-core-card.d.ts +37 -0
- package/types/neural-ui-core-chart.d.ts +236 -0
- package/types/neural-ui-core-checkbox.d.ts +33 -0
- package/types/neural-ui-core-chip.d.ts +53 -0
- package/types/neural-ui-core-code-block.d.ts +55 -0
- package/types/neural-ui-core-color-picker.d.ts +55 -0
- package/types/neural-ui-core-command-palette.d.ts +56 -0
- package/types/neural-ui-core-confirm-dialog.d.ts +50 -0
- package/types/neural-ui-core-context-menu.d.ts +66 -0
- package/types/neural-ui-core-dashboard-grid.d.ts +41 -0
- package/types/neural-ui-core-date-input.d.ts +178 -0
- package/types/neural-ui-core-divider.d.ts +20 -0
- package/types/neural-ui-core-empty-state.d.ts +32 -0
- package/types/neural-ui-core-filter-bar.d.ts +49 -0
- package/types/neural-ui-core-icon.d.ts +33 -0
- package/types/neural-ui-core-image-viewer.d.ts +67 -0
- package/types/neural-ui-core-input-otp.d.ts +49 -0
- package/types/neural-ui-core-input.d.ts +86 -0
- package/types/neural-ui-core-knob.d.ts +68 -0
- package/types/neural-ui-core-meter-group.d.ts +52 -0
- package/types/neural-ui-core-modal.d.ts +54 -0
- package/types/neural-ui-core-multiselect.d.ts +129 -0
- package/types/neural-ui-core-nav.d.ts +69 -0
- package/types/neural-ui-core-notification-center.d.ts +60 -0
- package/types/neural-ui-core-number-input.d.ts +63 -0
- package/types/neural-ui-core-pagination.d.ts +30 -0
- package/types/neural-ui-core-popover.d.ts +73 -0
- package/types/neural-ui-core-progress-bar.d.ts +35 -0
- package/types/neural-ui-core-radio.d.ts +51 -0
- package/types/neural-ui-core-rating.d.ts +34 -0
- package/types/neural-ui-core-select.d.ts +161 -0
- package/types/neural-ui-core-sidebar.d.ts +57 -0
- package/types/neural-ui-core-skeleton.d.ts +22 -0
- package/types/neural-ui-core-slider.d.ts +42 -0
- package/types/neural-ui-core-spinner.d.ts +38 -0
- package/types/neural-ui-core-split-button.d.ts +65 -0
- package/types/neural-ui-core-splitter.d.ts +28 -0
- package/types/neural-ui-core-stats-card.d.ts +39 -0
- package/types/neural-ui-core-stepper.d.ts +51 -0
- package/types/neural-ui-core-switch.d.ts +34 -0
- package/types/neural-ui-core-table.d.ts +282 -0
- package/types/neural-ui-core-tabs.d.ts +76 -0
- package/types/neural-ui-core-textarea.d.ts +52 -0
- package/types/neural-ui-core-timeline.d.ts +33 -0
- package/types/neural-ui-core-toast.d.ts +70 -0
- package/types/neural-ui-core-toggle-button-group.d.ts +63 -0
- package/types/neural-ui-core-toolbar.d.ts +36 -0
- package/types/neural-ui-core-tooltip.d.ts +48 -0
- package/types/neural-ui-core-url-state.d.ts +58 -0
- package/types/neural-ui-core-virtual-list.d.ts +60 -0
- package/types/neural-ui-core.d.ts +5 -2107
- package/url-state/package.json +4 -0
- package/virtual-list/package.json +4 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { input, computed, ChangeDetectionStrategy, ViewEncapsulation, Component } from '@angular/core';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* NeuralUI Spinner Component
|
|
6
|
+
*
|
|
7
|
+
* Indicador de carga circular animado para estados de espera.
|
|
8
|
+
* Permite personalizar color via severity o color CSS directo.
|
|
9
|
+
*
|
|
10
|
+
* Uso básico:
|
|
11
|
+
* <neu-spinner />
|
|
12
|
+
*
|
|
13
|
+
* Con severity:
|
|
14
|
+
* <neu-spinner severity="success" size="48px" />
|
|
15
|
+
*
|
|
16
|
+
* Con color personalizado:
|
|
17
|
+
* <neu-spinner color="#ff6b35" strokeWidth="6" />
|
|
18
|
+
*/
|
|
19
|
+
class NeuSpinnerComponent {
|
|
20
|
+
/** Variante de color semántica / Semantic color variant */
|
|
21
|
+
severity = input('primary', ...(ngDevMode ? [{ debugName: "severity" }] : /* istanbul ignore next */ []));
|
|
22
|
+
/** Color CSS directo — sobreescribe severity / Direct CSS color — overrides severity */
|
|
23
|
+
color = input('', ...(ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []));
|
|
24
|
+
/** Grosor del trazo SVG (unidades SVG) / SVG stroke width (SVG units) */
|
|
25
|
+
strokeWidth = input('4', ...(ngDevMode ? [{ debugName: "strokeWidth" }] : /* istanbul ignore next */ []));
|
|
26
|
+
/** Tamaño del spinner (CSS: '40px', '2rem', etc.) / Spinner size (CSS: '40px', '2rem', etc.) */
|
|
27
|
+
size = input('40px', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
28
|
+
/** Duración de la animación de rotación / Rotation animation duration */
|
|
29
|
+
animationDuration = input('1s', ...(ngDevMode ? [{ debugName: "animationDuration" }] : /* istanbul ignore next */ []));
|
|
30
|
+
/** Texto accesible para lectores de pantalla / Accessible text for screen readers */
|
|
31
|
+
ariaLabel = input('Cargando...', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
|
|
32
|
+
_severityColor = computed(() => {
|
|
33
|
+
const map = {
|
|
34
|
+
primary: 'var(--neu-primary)',
|
|
35
|
+
success: 'var(--neu-success)',
|
|
36
|
+
warning: 'var(--neu-warning)',
|
|
37
|
+
danger: 'var(--neu-danger)',
|
|
38
|
+
info: 'var(--neu-info)',
|
|
39
|
+
};
|
|
40
|
+
return map[this.severity()];
|
|
41
|
+
}, ...(ngDevMode ? [{ debugName: "_severityColor" }] : /* istanbul ignore next */ []));
|
|
42
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: NeuSpinnerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
43
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.8", type: NeuSpinnerComponent, isStandalone: true, selector: "neu-spinner", inputs: { severity: { classPropertyName: "severity", publicName: "severity", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, strokeWidth: { classPropertyName: "strokeWidth", publicName: "strokeWidth", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, animationDuration: { classPropertyName: "animationDuration", publicName: "animationDuration", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "neu-spinner-host" }, ngImport: i0, template: `
|
|
44
|
+
<svg
|
|
45
|
+
class="neu-spinner"
|
|
46
|
+
[class]="'neu-spinner--' + severity()"
|
|
47
|
+
[style.width]="size()"
|
|
48
|
+
[style.height]="size()"
|
|
49
|
+
[style.animation-duration]="animationDuration()"
|
|
50
|
+
viewBox="25 25 50 50"
|
|
51
|
+
aria-hidden="true"
|
|
52
|
+
>
|
|
53
|
+
<circle
|
|
54
|
+
class="neu-spinner__track"
|
|
55
|
+
cx="50"
|
|
56
|
+
cy="50"
|
|
57
|
+
r="20"
|
|
58
|
+
fill="none"
|
|
59
|
+
[attr.stroke-width]="strokeWidth()"
|
|
60
|
+
/>
|
|
61
|
+
<circle
|
|
62
|
+
class="neu-spinner__arc"
|
|
63
|
+
cx="50"
|
|
64
|
+
cy="50"
|
|
65
|
+
r="20"
|
|
66
|
+
fill="none"
|
|
67
|
+
[attr.stroke-width]="strokeWidth()"
|
|
68
|
+
[style.stroke]="color() || null"
|
|
69
|
+
/>
|
|
70
|
+
</svg>
|
|
71
|
+
<span class="cdk-visually-hidden">{{ ariaLabel() }}</span>
|
|
72
|
+
`, isInline: true, styles: [".neu-spinner-host{display:inline-flex;align-items:center;justify-content:center}.neu-spinner{animation:neu-spinner-rotate linear infinite;animation-duration:inherit}.neu-spinner__track{stroke:var(--neu-border);opacity:.3}.neu-spinner__arc{stroke-dasharray:89,200;stroke-dashoffset:-10;animation:neu-spinner-dash 1.5s ease-in-out infinite;stroke-linecap:round}.neu-spinner--primary .neu-spinner__arc{stroke:var(--neu-primary)}.neu-spinner--success .neu-spinner__arc{stroke:var(--neu-success)}.neu-spinner--warning .neu-spinner__arc{stroke:var(--neu-warning)}.neu-spinner--danger .neu-spinner__arc{stroke:var(--neu-danger)}.neu-spinner--info .neu-spinner__arc{stroke:var(--neu-info)}@keyframes neu-spinner-rotate{to{transform:rotate(360deg)}}@keyframes neu-spinner-dash{0%{stroke-dasharray:1,200;stroke-dashoffset:0}50%{stroke-dasharray:89,200;stroke-dashoffset:-35px}to{stroke-dasharray:89,200;stroke-dashoffset:-124px}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
73
|
+
}
|
|
74
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: NeuSpinnerComponent, decorators: [{
|
|
75
|
+
type: Component,
|
|
76
|
+
args: [{ selector: 'neu-spinner', imports: [], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'neu-spinner-host' }, template: `
|
|
77
|
+
<svg
|
|
78
|
+
class="neu-spinner"
|
|
79
|
+
[class]="'neu-spinner--' + severity()"
|
|
80
|
+
[style.width]="size()"
|
|
81
|
+
[style.height]="size()"
|
|
82
|
+
[style.animation-duration]="animationDuration()"
|
|
83
|
+
viewBox="25 25 50 50"
|
|
84
|
+
aria-hidden="true"
|
|
85
|
+
>
|
|
86
|
+
<circle
|
|
87
|
+
class="neu-spinner__track"
|
|
88
|
+
cx="50"
|
|
89
|
+
cy="50"
|
|
90
|
+
r="20"
|
|
91
|
+
fill="none"
|
|
92
|
+
[attr.stroke-width]="strokeWidth()"
|
|
93
|
+
/>
|
|
94
|
+
<circle
|
|
95
|
+
class="neu-spinner__arc"
|
|
96
|
+
cx="50"
|
|
97
|
+
cy="50"
|
|
98
|
+
r="20"
|
|
99
|
+
fill="none"
|
|
100
|
+
[attr.stroke-width]="strokeWidth()"
|
|
101
|
+
[style.stroke]="color() || null"
|
|
102
|
+
/>
|
|
103
|
+
</svg>
|
|
104
|
+
<span class="cdk-visually-hidden">{{ ariaLabel() }}</span>
|
|
105
|
+
`, styles: [".neu-spinner-host{display:inline-flex;align-items:center;justify-content:center}.neu-spinner{animation:neu-spinner-rotate linear infinite;animation-duration:inherit}.neu-spinner__track{stroke:var(--neu-border);opacity:.3}.neu-spinner__arc{stroke-dasharray:89,200;stroke-dashoffset:-10;animation:neu-spinner-dash 1.5s ease-in-out infinite;stroke-linecap:round}.neu-spinner--primary .neu-spinner__arc{stroke:var(--neu-primary)}.neu-spinner--success .neu-spinner__arc{stroke:var(--neu-success)}.neu-spinner--warning .neu-spinner__arc{stroke:var(--neu-warning)}.neu-spinner--danger .neu-spinner__arc{stroke:var(--neu-danger)}.neu-spinner--info .neu-spinner__arc{stroke:var(--neu-info)}@keyframes neu-spinner-rotate{to{transform:rotate(360deg)}}@keyframes neu-spinner-dash{0%{stroke-dasharray:1,200;stroke-dashoffset:0}50%{stroke-dasharray:89,200;stroke-dashoffset:-35px}to{stroke-dasharray:89,200;stroke-dashoffset:-124px}}\n"] }]
|
|
106
|
+
}], propDecorators: { severity: [{ type: i0.Input, args: [{ isSignal: true, alias: "severity", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], strokeWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "strokeWidth", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], animationDuration: [{ type: i0.Input, args: [{ isSignal: true, alias: "animationDuration", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }] } });
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Generated bundle index. Do not edit.
|
|
110
|
+
*/
|
|
111
|
+
|
|
112
|
+
export { NeuSpinnerComponent };
|
|
113
|
+
//# sourceMappingURL=neural-ui-core-spinner.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"neural-ui-core-spinner.mjs","sources":["../../../../projects/ui-core/spinner/neu-spinner.component.ts","../../../../projects/ui-core/spinner/neural-ui-core-spinner.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n ViewEncapsulation,\n computed,\n input,\n} from '@angular/core';\n\nexport type NeuSpinnerSeverity = 'primary' | 'success' | 'warning' | 'danger' | 'info';\n\n/**\n * NeuralUI Spinner Component\n *\n * Indicador de carga circular animado para estados de espera.\n * Permite personalizar color via severity o color CSS directo.\n *\n * Uso básico:\n * <neu-spinner />\n *\n * Con severity:\n * <neu-spinner severity=\"success\" size=\"48px\" />\n *\n * Con color personalizado:\n * <neu-spinner color=\"#ff6b35\" strokeWidth=\"6\" />\n */\n@Component({\n selector: 'neu-spinner',\n imports: [],\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: { class: 'neu-spinner-host' },\n template: `\n <svg\n class=\"neu-spinner\"\n [class]=\"'neu-spinner--' + severity()\"\n [style.width]=\"size()\"\n [style.height]=\"size()\"\n [style.animation-duration]=\"animationDuration()\"\n viewBox=\"25 25 50 50\"\n aria-hidden=\"true\"\n >\n <circle\n class=\"neu-spinner__track\"\n cx=\"50\"\n cy=\"50\"\n r=\"20\"\n fill=\"none\"\n [attr.stroke-width]=\"strokeWidth()\"\n />\n <circle\n class=\"neu-spinner__arc\"\n cx=\"50\"\n cy=\"50\"\n r=\"20\"\n fill=\"none\"\n [attr.stroke-width]=\"strokeWidth()\"\n [style.stroke]=\"color() || null\"\n />\n </svg>\n <span class=\"cdk-visually-hidden\">{{ ariaLabel() }}</span>\n `,\n styleUrl: './neu-spinner.component.scss',\n})\nexport class NeuSpinnerComponent {\n /** Variante de color semántica / Semantic color variant */\n severity = input<NeuSpinnerSeverity>('primary');\n\n /** Color CSS directo — sobreescribe severity / Direct CSS color — overrides severity */\n color = input<string>('');\n\n /** Grosor del trazo SVG (unidades SVG) / SVG stroke width (SVG units) */\n strokeWidth = input<string>('4');\n\n /** Tamaño del spinner (CSS: '40px', '2rem', etc.) / Spinner size (CSS: '40px', '2rem', etc.) */\n size = input<string>('40px');\n\n /** Duración de la animación de rotación / Rotation animation duration */\n animationDuration = input<string>('1s');\n\n /** Texto accesible para lectores de pantalla / Accessible text for screen readers */\n ariaLabel = input<string>('Cargando...');\n\n readonly _severityColor = computed(() => {\n const map: Record<NeuSpinnerSeverity, string> = {\n primary: 'var(--neu-primary)',\n success: 'var(--neu-success)',\n warning: 'var(--neu-warning)',\n danger: 'var(--neu-danger)',\n info: 'var(--neu-info)',\n };\n return map[this.severity()];\n });\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public_api';\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { inject, ElementRef, input, output, signal, computed, ChangeDetectionStrategy, ViewEncapsulation, Component } from '@angular/core';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* NeuralUI SplitButton Component
|
|
6
|
+
*
|
|
7
|
+
* Botón principal con un dropdown de acciones adicionales. / Primary button with a dropdown of additional actions.
|
|
8
|
+
*
|
|
9
|
+
* Uso:
|
|
10
|
+
* <neu-split-button
|
|
11
|
+
* label="Guardar"
|
|
12
|
+
* [actions]="actions"
|
|
13
|
+
* (primaryClick)="save()"
|
|
14
|
+
* (actionClick)="onAction($event)"
|
|
15
|
+
* />
|
|
16
|
+
*/
|
|
17
|
+
class NeuSplitButtonComponent {
|
|
18
|
+
el = inject(ElementRef);
|
|
19
|
+
/** Texto del botón principal / Primary button text */
|
|
20
|
+
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
21
|
+
/** Variante visual / Visual variant */
|
|
22
|
+
variant = input('primary', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
|
|
23
|
+
/** Tamaño / Size */
|
|
24
|
+
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
25
|
+
/** Deshabilita todo el componente / Disables the entire component */
|
|
26
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
27
|
+
/** Muestra spinner en el botón principal / Shows spinner on the primary button */
|
|
28
|
+
loading = input(false, ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
|
|
29
|
+
/** Acciones del dropdown / Dropdown actions */
|
|
30
|
+
actions = input([], ...(ngDevMode ? [{ debugName: "actions" }] : /* istanbul ignore next */ []));
|
|
31
|
+
/** Aria-label del botón de desplegable / Aria-label for the dropdown button */
|
|
32
|
+
moreActionsAriaLabel = input('Más opciones', ...(ngDevMode ? [{ debugName: "moreActionsAriaLabel" }] : /* istanbul ignore next */ []));
|
|
33
|
+
/** Aria-label del menú desplegable / Aria-label for the dropdown menu */
|
|
34
|
+
actionsAriaLabel = input('Acciones', ...(ngDevMode ? [{ debugName: "actionsAriaLabel" }] : /* istanbul ignore next */ []));
|
|
35
|
+
/** Emite al hacer click en el botón principal / Emits on primary button click */
|
|
36
|
+
primaryClick = output();
|
|
37
|
+
/** Emite al seleccionar una acción del dropdown / Emits when a dropdown action is selected */
|
|
38
|
+
actionClick = output();
|
|
39
|
+
isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
|
|
40
|
+
isDisabled = computed(() => this.disabled() || this.loading(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
|
|
41
|
+
mainClasses = computed(() => `neu-button neu-button--${this.variant()} neu-button--${this.size()}${this.loading() ? ' neu-button--loading' : ''}`, ...(ngDevMode ? [{ debugName: "mainClasses" }] : /* istanbul ignore next */ []));
|
|
42
|
+
chevronClasses = computed(() => `neu-button neu-button--${this.variant()} neu-button--${this.size()}`, ...(ngDevMode ? [{ debugName: "chevronClasses" }] : /* istanbul ignore next */ []));
|
|
43
|
+
toggleDropdown(event) {
|
|
44
|
+
event.stopPropagation();
|
|
45
|
+
this.isOpen.update((v) => !v);
|
|
46
|
+
}
|
|
47
|
+
closeDropdown() {
|
|
48
|
+
this.isOpen.set(false);
|
|
49
|
+
}
|
|
50
|
+
onDocumentClick(event) {
|
|
51
|
+
if (!this.el.nativeElement.contains(event.target))
|
|
52
|
+
this.closeDropdown();
|
|
53
|
+
}
|
|
54
|
+
onPrimaryClick(event) {
|
|
55
|
+
if (this.isDisabled())
|
|
56
|
+
return;
|
|
57
|
+
this.primaryClick.emit(event);
|
|
58
|
+
}
|
|
59
|
+
onActionClick(action) {
|
|
60
|
+
if (action.disabled)
|
|
61
|
+
return;
|
|
62
|
+
this.closeDropdown();
|
|
63
|
+
this.actionClick.emit(action);
|
|
64
|
+
}
|
|
65
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: NeuSplitButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
66
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: NeuSplitButtonComponent, isStandalone: true, selector: "neu-split-button", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, actions: { classPropertyName: "actions", publicName: "actions", isSignal: true, isRequired: false, transformFunction: null }, moreActionsAriaLabel: { classPropertyName: "moreActionsAriaLabel", publicName: "moreActionsAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, actionsAriaLabel: { classPropertyName: "actionsAriaLabel", publicName: "actionsAriaLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { primaryClick: "primaryClick", actionClick: "actionClick" }, host: { listeners: { "document:click": "onDocumentClick($event)", "keydown.escape": "closeDropdown()" }, classAttribute: "neu-split-button-host" }, ngImport: i0, template: `
|
|
67
|
+
<div class="neu-split-button" [class.neu-split-button--disabled]="isDisabled()">
|
|
68
|
+
<!-- Botón principal -->
|
|
69
|
+
<button
|
|
70
|
+
class="neu-split-button__main"
|
|
71
|
+
[class]="mainClasses()"
|
|
72
|
+
type="button"
|
|
73
|
+
[disabled]="isDisabled() || null"
|
|
74
|
+
[attr.aria-disabled]="isDisabled()"
|
|
75
|
+
[attr.aria-busy]="loading()"
|
|
76
|
+
(click)="onPrimaryClick($event)"
|
|
77
|
+
>
|
|
78
|
+
@if (loading()) {
|
|
79
|
+
<span class="neu-button__spinner" aria-hidden="true">
|
|
80
|
+
<svg viewBox="0 0 24 24" fill="none">
|
|
81
|
+
<circle
|
|
82
|
+
cx="12"
|
|
83
|
+
cy="12"
|
|
84
|
+
r="10"
|
|
85
|
+
stroke="currentColor"
|
|
86
|
+
stroke-width="3"
|
|
87
|
+
stroke-linecap="round"
|
|
88
|
+
stroke-dasharray="31.416"
|
|
89
|
+
stroke-dashoffset="10"
|
|
90
|
+
/>
|
|
91
|
+
</svg>
|
|
92
|
+
</span>
|
|
93
|
+
}
|
|
94
|
+
{{ label() }}
|
|
95
|
+
</button>
|
|
96
|
+
|
|
97
|
+
<!-- Separador -->
|
|
98
|
+
<span class="neu-split-button__divider" aria-hidden="true"></span>
|
|
99
|
+
|
|
100
|
+
<!-- Chevron trigger -->
|
|
101
|
+
<button
|
|
102
|
+
class="neu-split-button__chevron"
|
|
103
|
+
[class]="chevronClasses()"
|
|
104
|
+
type="button"
|
|
105
|
+
[disabled]="isDisabled() || null"
|
|
106
|
+
[attr.aria-haspopup]="'menu'"
|
|
107
|
+
[attr.aria-expanded]="isOpen()"
|
|
108
|
+
[attr.aria-label]="moreActionsAriaLabel()"
|
|
109
|
+
(click)="toggleDropdown($event)"
|
|
110
|
+
>
|
|
111
|
+
<svg
|
|
112
|
+
viewBox="0 0 24 24"
|
|
113
|
+
fill="none"
|
|
114
|
+
stroke="currentColor"
|
|
115
|
+
stroke-width="2.5"
|
|
116
|
+
stroke-linecap="round"
|
|
117
|
+
stroke-linejoin="round"
|
|
118
|
+
aria-hidden="true"
|
|
119
|
+
>
|
|
120
|
+
<polyline points="6 9 12 15 18 9" />
|
|
121
|
+
</svg>
|
|
122
|
+
</button>
|
|
123
|
+
|
|
124
|
+
<!-- Dropdown de acciones -->
|
|
125
|
+
@if (isOpen()) {
|
|
126
|
+
<div
|
|
127
|
+
class="neu-split-button__dropdown"
|
|
128
|
+
role="menu"
|
|
129
|
+
[attr.aria-label]="actionsAriaLabel()"
|
|
130
|
+
(click)="$event.stopPropagation()"
|
|
131
|
+
>
|
|
132
|
+
@for (action of actions(); track action.id) {
|
|
133
|
+
@if (action.divider) {
|
|
134
|
+
<div class="neu-split-button__dropdown-sep" role="separator" aria-hidden="true"></div>
|
|
135
|
+
}
|
|
136
|
+
<button
|
|
137
|
+
class="neu-split-button__dropdown-item"
|
|
138
|
+
[class.neu-split-button__dropdown-item--disabled]="action.disabled"
|
|
139
|
+
type="button"
|
|
140
|
+
role="menuitem"
|
|
141
|
+
[disabled]="action.disabled || null"
|
|
142
|
+
[attr.aria-disabled]="action.disabled ? 'true' : null"
|
|
143
|
+
(click)="onActionClick(action)"
|
|
144
|
+
>
|
|
145
|
+
{{ action.label }}
|
|
146
|
+
</button>
|
|
147
|
+
}
|
|
148
|
+
</div>
|
|
149
|
+
}
|
|
150
|
+
</div>
|
|
151
|
+
`, isInline: true, styles: [".neu-button{display:inline-flex;align-items:center;justify-content:center;gap:var(--neu-space-2);border:1px solid transparent;border-radius:var(--neu-radius);font-family:var(--neu-font-sans);font-weight:500;line-height:1;cursor:pointer;text-decoration:none;white-space:nowrap;-webkit-user-select:none;user-select:none;transition:background-color var(--neu-transition),border-color var(--neu-transition),color var(--neu-transition),box-shadow var(--neu-transition),opacity var(--neu-transition);outline:none}.neu-button:focus-visible{box-shadow:var(--neu-focus-ring-strong)}.neu-button--sm{padding:var(--neu-space-2) var(--neu-space-3);font-size:var(--neu-text-sm);border-radius:var(--neu-radius-sm)}.neu-button--md{padding:var(--neu-space-2) var(--neu-space-5);font-size:var(--neu-text-base)}@media(min-width:400px){.neu-button--md{padding:.625rem var(--neu-space-6)}}.neu-button--lg{padding:var(--neu-space-3) var(--neu-space-8);font-size:var(--neu-text-lg)}.neu-button--full-width{width:100%}.neu-button--primary{background:var(--neu-primary);color:var(--neu-primary-fg);border-color:var(--neu-primary)}.neu-button--primary:hover:not(:disabled):not(.neu-button--disabled){background:var(--neu-primary-dark);border-color:var(--neu-primary-dark);box-shadow:var(--neu-shadow-glow)}.neu-button--primary:active:not(:disabled){background:var(--neu-primary-dark);transform:translateY(1px)}.neu-button--secondary{background:var(--neu-secondary);color:var(--neu-secondary-fg);border-color:var(--neu-secondary)}.neu-button--secondary:hover:not(:disabled):not(.neu-button--disabled){background:var(--neu-secondary-dark);border-color:var(--neu-secondary-dark)}.neu-button--outline{background:transparent;color:var(--neu-primary-light);border-color:var(--neu-primary)}.neu-button--outline:hover:not(:disabled):not(.neu-button--disabled){background:var(--neu-primary-50);border-color:var(--neu-primary-light)}.neu-button--ghost{background:transparent;color:var(--neu-text-muted);border-color:transparent}.neu-button--ghost:hover:not(:disabled):not(.neu-button--disabled){background:var(--neu-surface-2);color:var(--neu-text)}.neu-button--danger{background:var(--neu-error);color:var(--neu-primary-fg);border-color:var(--neu-error)}.neu-button--danger:hover:not(:disabled):not(.neu-button--disabled){background:#dc2626;border-color:#dc2626}.neu-button--disabled,.neu-button:disabled{opacity:.45;cursor:not-allowed;pointer-events:none}.neu-button--loading{cursor:wait;pointer-events:none}.neu-button--icon-only.neu-button--sm{width:30px;height:30px;padding:0}.neu-button--icon-only.neu-button--md{width:38px;height:38px;padding:0}.neu-button--icon-only.neu-button--lg{width:46px;height:46px;padding:0}.neu-button__spinner{display:inline-flex;flex-shrink:0;width:1em;height:1em}.neu-button__spinner svg{width:100%;height:100%;animation:neu-spin .8s linear infinite}@keyframes neu-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.neu-split-button-host{display:inline-block}.neu-split-button{display:inline-flex;align-items:stretch}.neu-split-button--disabled{opacity:.6;pointer-events:none}.neu-split-button .neu-split-button__main{border-top-right-radius:0!important;border-bottom-right-radius:0!important;border-right:none!important;flex:1}.neu-split-button .neu-split-button__chevron{border-top-left-radius:0!important;border-bottom-left-radius:0!important;padding-inline:10px!important;min-width:auto}.neu-split-button .neu-split-button__chevron svg{width:14px;height:14px;display:block}.neu-split-button__divider{width:1px;background:var(--neu-split-button-primary-divider);align-self:stretch;flex-shrink:0}.neu-button--secondary .neu-split-button__divider,.neu-button--ghost .neu-split-button__divider,.neu-button--outline .neu-split-button__divider{background:var(--neu-border)}.neu-split-button__dropdown{position:absolute;top:calc(100% + 6px);right:0;z-index:200;min-width:180px;background:var(--neu-surface);border:1.5px solid var(--neu-border);border-radius:var(--neu-radius);box-shadow:var(--neu-shadow-lg);padding:var(--neu-space-1) 0;animation:neu-split-btn-in .1s ease}@keyframes neu-split-btn-in{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}.neu-split-button{position:relative}.neu-split-button__dropdown-item{display:flex;align-items:center;width:100%;padding:9px var(--neu-space-4);border:none;background:none;font-family:var(--neu-font-sans);font-size:var(--neu-text-sm);color:var(--neu-text);cursor:pointer;text-align:left;transition:background var(--neu-transition)}.neu-split-button__dropdown-item:hover:not(:disabled):not(.neu-split-button__dropdown-item--disabled){background:var(--neu-surface-2)}.neu-split-button__dropdown-item--disabled,.neu-split-button__dropdown-item:disabled{color:var(--neu-text-disabled);cursor:not-allowed}.neu-split-button__dropdown-sep{height:1px;background:var(--neu-border);margin:var(--neu-space-1) 0}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
152
|
+
}
|
|
153
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: NeuSplitButtonComponent, decorators: [{
|
|
154
|
+
type: Component,
|
|
155
|
+
args: [{ selector: 'neu-split-button', imports: [], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
156
|
+
class: 'neu-split-button-host',
|
|
157
|
+
'(document:click)': 'onDocumentClick($event)',
|
|
158
|
+
'(keydown.escape)': 'closeDropdown()',
|
|
159
|
+
}, template: `
|
|
160
|
+
<div class="neu-split-button" [class.neu-split-button--disabled]="isDisabled()">
|
|
161
|
+
<!-- Botón principal -->
|
|
162
|
+
<button
|
|
163
|
+
class="neu-split-button__main"
|
|
164
|
+
[class]="mainClasses()"
|
|
165
|
+
type="button"
|
|
166
|
+
[disabled]="isDisabled() || null"
|
|
167
|
+
[attr.aria-disabled]="isDisabled()"
|
|
168
|
+
[attr.aria-busy]="loading()"
|
|
169
|
+
(click)="onPrimaryClick($event)"
|
|
170
|
+
>
|
|
171
|
+
@if (loading()) {
|
|
172
|
+
<span class="neu-button__spinner" aria-hidden="true">
|
|
173
|
+
<svg viewBox="0 0 24 24" fill="none">
|
|
174
|
+
<circle
|
|
175
|
+
cx="12"
|
|
176
|
+
cy="12"
|
|
177
|
+
r="10"
|
|
178
|
+
stroke="currentColor"
|
|
179
|
+
stroke-width="3"
|
|
180
|
+
stroke-linecap="round"
|
|
181
|
+
stroke-dasharray="31.416"
|
|
182
|
+
stroke-dashoffset="10"
|
|
183
|
+
/>
|
|
184
|
+
</svg>
|
|
185
|
+
</span>
|
|
186
|
+
}
|
|
187
|
+
{{ label() }}
|
|
188
|
+
</button>
|
|
189
|
+
|
|
190
|
+
<!-- Separador -->
|
|
191
|
+
<span class="neu-split-button__divider" aria-hidden="true"></span>
|
|
192
|
+
|
|
193
|
+
<!-- Chevron trigger -->
|
|
194
|
+
<button
|
|
195
|
+
class="neu-split-button__chevron"
|
|
196
|
+
[class]="chevronClasses()"
|
|
197
|
+
type="button"
|
|
198
|
+
[disabled]="isDisabled() || null"
|
|
199
|
+
[attr.aria-haspopup]="'menu'"
|
|
200
|
+
[attr.aria-expanded]="isOpen()"
|
|
201
|
+
[attr.aria-label]="moreActionsAriaLabel()"
|
|
202
|
+
(click)="toggleDropdown($event)"
|
|
203
|
+
>
|
|
204
|
+
<svg
|
|
205
|
+
viewBox="0 0 24 24"
|
|
206
|
+
fill="none"
|
|
207
|
+
stroke="currentColor"
|
|
208
|
+
stroke-width="2.5"
|
|
209
|
+
stroke-linecap="round"
|
|
210
|
+
stroke-linejoin="round"
|
|
211
|
+
aria-hidden="true"
|
|
212
|
+
>
|
|
213
|
+
<polyline points="6 9 12 15 18 9" />
|
|
214
|
+
</svg>
|
|
215
|
+
</button>
|
|
216
|
+
|
|
217
|
+
<!-- Dropdown de acciones -->
|
|
218
|
+
@if (isOpen()) {
|
|
219
|
+
<div
|
|
220
|
+
class="neu-split-button__dropdown"
|
|
221
|
+
role="menu"
|
|
222
|
+
[attr.aria-label]="actionsAriaLabel()"
|
|
223
|
+
(click)="$event.stopPropagation()"
|
|
224
|
+
>
|
|
225
|
+
@for (action of actions(); track action.id) {
|
|
226
|
+
@if (action.divider) {
|
|
227
|
+
<div class="neu-split-button__dropdown-sep" role="separator" aria-hidden="true"></div>
|
|
228
|
+
}
|
|
229
|
+
<button
|
|
230
|
+
class="neu-split-button__dropdown-item"
|
|
231
|
+
[class.neu-split-button__dropdown-item--disabled]="action.disabled"
|
|
232
|
+
type="button"
|
|
233
|
+
role="menuitem"
|
|
234
|
+
[disabled]="action.disabled || null"
|
|
235
|
+
[attr.aria-disabled]="action.disabled ? 'true' : null"
|
|
236
|
+
(click)="onActionClick(action)"
|
|
237
|
+
>
|
|
238
|
+
{{ action.label }}
|
|
239
|
+
</button>
|
|
240
|
+
}
|
|
241
|
+
</div>
|
|
242
|
+
}
|
|
243
|
+
</div>
|
|
244
|
+
`, styles: [".neu-button{display:inline-flex;align-items:center;justify-content:center;gap:var(--neu-space-2);border:1px solid transparent;border-radius:var(--neu-radius);font-family:var(--neu-font-sans);font-weight:500;line-height:1;cursor:pointer;text-decoration:none;white-space:nowrap;-webkit-user-select:none;user-select:none;transition:background-color var(--neu-transition),border-color var(--neu-transition),color var(--neu-transition),box-shadow var(--neu-transition),opacity var(--neu-transition);outline:none}.neu-button:focus-visible{box-shadow:var(--neu-focus-ring-strong)}.neu-button--sm{padding:var(--neu-space-2) var(--neu-space-3);font-size:var(--neu-text-sm);border-radius:var(--neu-radius-sm)}.neu-button--md{padding:var(--neu-space-2) var(--neu-space-5);font-size:var(--neu-text-base)}@media(min-width:400px){.neu-button--md{padding:.625rem var(--neu-space-6)}}.neu-button--lg{padding:var(--neu-space-3) var(--neu-space-8);font-size:var(--neu-text-lg)}.neu-button--full-width{width:100%}.neu-button--primary{background:var(--neu-primary);color:var(--neu-primary-fg);border-color:var(--neu-primary)}.neu-button--primary:hover:not(:disabled):not(.neu-button--disabled){background:var(--neu-primary-dark);border-color:var(--neu-primary-dark);box-shadow:var(--neu-shadow-glow)}.neu-button--primary:active:not(:disabled){background:var(--neu-primary-dark);transform:translateY(1px)}.neu-button--secondary{background:var(--neu-secondary);color:var(--neu-secondary-fg);border-color:var(--neu-secondary)}.neu-button--secondary:hover:not(:disabled):not(.neu-button--disabled){background:var(--neu-secondary-dark);border-color:var(--neu-secondary-dark)}.neu-button--outline{background:transparent;color:var(--neu-primary-light);border-color:var(--neu-primary)}.neu-button--outline:hover:not(:disabled):not(.neu-button--disabled){background:var(--neu-primary-50);border-color:var(--neu-primary-light)}.neu-button--ghost{background:transparent;color:var(--neu-text-muted);border-color:transparent}.neu-button--ghost:hover:not(:disabled):not(.neu-button--disabled){background:var(--neu-surface-2);color:var(--neu-text)}.neu-button--danger{background:var(--neu-error);color:var(--neu-primary-fg);border-color:var(--neu-error)}.neu-button--danger:hover:not(:disabled):not(.neu-button--disabled){background:#dc2626;border-color:#dc2626}.neu-button--disabled,.neu-button:disabled{opacity:.45;cursor:not-allowed;pointer-events:none}.neu-button--loading{cursor:wait;pointer-events:none}.neu-button--icon-only.neu-button--sm{width:30px;height:30px;padding:0}.neu-button--icon-only.neu-button--md{width:38px;height:38px;padding:0}.neu-button--icon-only.neu-button--lg{width:46px;height:46px;padding:0}.neu-button__spinner{display:inline-flex;flex-shrink:0;width:1em;height:1em}.neu-button__spinner svg{width:100%;height:100%;animation:neu-spin .8s linear infinite}@keyframes neu-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.neu-split-button-host{display:inline-block}.neu-split-button{display:inline-flex;align-items:stretch}.neu-split-button--disabled{opacity:.6;pointer-events:none}.neu-split-button .neu-split-button__main{border-top-right-radius:0!important;border-bottom-right-radius:0!important;border-right:none!important;flex:1}.neu-split-button .neu-split-button__chevron{border-top-left-radius:0!important;border-bottom-left-radius:0!important;padding-inline:10px!important;min-width:auto}.neu-split-button .neu-split-button__chevron svg{width:14px;height:14px;display:block}.neu-split-button__divider{width:1px;background:var(--neu-split-button-primary-divider);align-self:stretch;flex-shrink:0}.neu-button--secondary .neu-split-button__divider,.neu-button--ghost .neu-split-button__divider,.neu-button--outline .neu-split-button__divider{background:var(--neu-border)}.neu-split-button__dropdown{position:absolute;top:calc(100% + 6px);right:0;z-index:200;min-width:180px;background:var(--neu-surface);border:1.5px solid var(--neu-border);border-radius:var(--neu-radius);box-shadow:var(--neu-shadow-lg);padding:var(--neu-space-1) 0;animation:neu-split-btn-in .1s ease}@keyframes neu-split-btn-in{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}.neu-split-button{position:relative}.neu-split-button__dropdown-item{display:flex;align-items:center;width:100%;padding:9px var(--neu-space-4);border:none;background:none;font-family:var(--neu-font-sans);font-size:var(--neu-text-sm);color:var(--neu-text);cursor:pointer;text-align:left;transition:background var(--neu-transition)}.neu-split-button__dropdown-item:hover:not(:disabled):not(.neu-split-button__dropdown-item--disabled){background:var(--neu-surface-2)}.neu-split-button__dropdown-item--disabled,.neu-split-button__dropdown-item:disabled{color:var(--neu-text-disabled);cursor:not-allowed}.neu-split-button__dropdown-sep{height:1px;background:var(--neu-border);margin:var(--neu-space-1) 0}\n"] }]
|
|
245
|
+
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], actions: [{ type: i0.Input, args: [{ isSignal: true, alias: "actions", required: false }] }], moreActionsAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "moreActionsAriaLabel", required: false }] }], actionsAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "actionsAriaLabel", required: false }] }], primaryClick: [{ type: i0.Output, args: ["primaryClick"] }], actionClick: [{ type: i0.Output, args: ["actionClick"] }] } });
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Generated bundle index. Do not edit.
|
|
249
|
+
*/
|
|
250
|
+
|
|
251
|
+
export { NeuSplitButtonComponent };
|
|
252
|
+
//# sourceMappingURL=neural-ui-core-split-button.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"neural-ui-core-split-button.mjs","sources":["../../../../projects/ui-core/split-button/neu-split-button.component.ts","../../../../projects/ui-core/split-button/neural-ui-core-split-button.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n ViewEncapsulation,\n computed,\n inject,\n input,\n output,\n signal,\n} from '@angular/core';\nimport { NeuButtonVariant, NeuButtonSize } from '@neural-ui/core/button';\n\nexport interface NeuSplitButtonAction {\n /** Identificador único de la acción / Unique action identifier */\n id: string;\n /** Texto visible / Visible text */\n label: string;\n /** Icono opcional (SVG string o nombre) / Optional icon (SVG string or name) */\n icon?: string;\n /** Deshabilita esta acción individualmente / Disables this action individually */\n disabled?: boolean;\n /** Separador visual encima de este item / Visual separator above this item */\n divider?: boolean;\n}\n\n/**\n * NeuralUI SplitButton Component\n *\n * Botón principal con un dropdown de acciones adicionales. / Primary button with a dropdown of additional actions.\n *\n * Uso:\n * <neu-split-button\n * label=\"Guardar\"\n * [actions]=\"actions\"\n * (primaryClick)=\"save()\"\n * (actionClick)=\"onAction($event)\"\n * />\n */\n@Component({\n selector: 'neu-split-button',\n imports: [],\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n class: 'neu-split-button-host',\n '(document:click)': 'onDocumentClick($event)',\n '(keydown.escape)': 'closeDropdown()',\n },\n template: `\n <div class=\"neu-split-button\" [class.neu-split-button--disabled]=\"isDisabled()\">\n <!-- Botón principal -->\n <button\n class=\"neu-split-button__main\"\n [class]=\"mainClasses()\"\n type=\"button\"\n [disabled]=\"isDisabled() || null\"\n [attr.aria-disabled]=\"isDisabled()\"\n [attr.aria-busy]=\"loading()\"\n (click)=\"onPrimaryClick($event)\"\n >\n @if (loading()) {\n <span class=\"neu-button__spinner\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\">\n <circle\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n stroke-linecap=\"round\"\n stroke-dasharray=\"31.416\"\n stroke-dashoffset=\"10\"\n />\n </svg>\n </span>\n }\n {{ label() }}\n </button>\n\n <!-- Separador -->\n <span class=\"neu-split-button__divider\" aria-hidden=\"true\"></span>\n\n <!-- Chevron trigger -->\n <button\n class=\"neu-split-button__chevron\"\n [class]=\"chevronClasses()\"\n type=\"button\"\n [disabled]=\"isDisabled() || null\"\n [attr.aria-haspopup]=\"'menu'\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-label]=\"moreActionsAriaLabel()\"\n (click)=\"toggleDropdown($event)\"\n >\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n </button>\n\n <!-- Dropdown de acciones -->\n @if (isOpen()) {\n <div\n class=\"neu-split-button__dropdown\"\n role=\"menu\"\n [attr.aria-label]=\"actionsAriaLabel()\"\n (click)=\"$event.stopPropagation()\"\n >\n @for (action of actions(); track action.id) {\n @if (action.divider) {\n <div class=\"neu-split-button__dropdown-sep\" role=\"separator\" aria-hidden=\"true\"></div>\n }\n <button\n class=\"neu-split-button__dropdown-item\"\n [class.neu-split-button__dropdown-item--disabled]=\"action.disabled\"\n type=\"button\"\n role=\"menuitem\"\n [disabled]=\"action.disabled || null\"\n [attr.aria-disabled]=\"action.disabled ? 'true' : null\"\n (click)=\"onActionClick(action)\"\n >\n {{ action.label }}\n </button>\n }\n </div>\n }\n </div>\n `,\n styleUrl: './neu-split-button.component.scss',\n})\nexport class NeuSplitButtonComponent {\n private readonly el = inject<ElementRef<HTMLElement>>(ElementRef);\n\n /** Texto del botón principal / Primary button text */\n label = input<string>('');\n\n /** Variante visual / Visual variant */\n variant = input<NeuButtonVariant>('primary');\n\n /** Tamaño / Size */\n size = input<NeuButtonSize>('md');\n\n /** Deshabilita todo el componente / Disables the entire component */\n disabled = input<boolean>(false);\n\n /** Muestra spinner en el botón principal / Shows spinner on the primary button */\n loading = input<boolean>(false);\n\n /** Acciones del dropdown / Dropdown actions */\n actions = input<NeuSplitButtonAction[]>([]);\n\n /** Aria-label del botón de desplegable / Aria-label for the dropdown button */\n moreActionsAriaLabel = input<string>('Más opciones');\n\n /** Aria-label del menú desplegable / Aria-label for the dropdown menu */\n actionsAriaLabel = input<string>('Acciones');\n\n /** Emite al hacer click en el botón principal / Emits on primary button click */\n primaryClick = output<MouseEvent>();\n\n /** Emite al seleccionar una acción del dropdown / Emits when a dropdown action is selected */\n actionClick = output<NeuSplitButtonAction>();\n\n readonly isOpen = signal(false);\n\n readonly isDisabled = computed(() => this.disabled() || this.loading());\n\n readonly mainClasses = computed(\n () =>\n `neu-button neu-button--${this.variant()} neu-button--${this.size()}${this.loading() ? ' neu-button--loading' : ''}`,\n );\n\n readonly chevronClasses = computed(\n () => `neu-button neu-button--${this.variant()} neu-button--${this.size()}`,\n );\n\n toggleDropdown(event: MouseEvent): void {\n event.stopPropagation();\n this.isOpen.update((v) => !v);\n }\n\n closeDropdown(): void {\n this.isOpen.set(false);\n }\n\n onDocumentClick(event: MouseEvent): void {\n if (!this.el.nativeElement.contains(event.target as Node)) this.closeDropdown();\n }\n\n onPrimaryClick(event: MouseEvent): void {\n if (this.isDisabled()) return;\n this.primaryClick.emit(event);\n }\n\n onActionClick(action: NeuSplitButtonAction): void {\n if (action.disabled) return;\n this.closeDropdown();\n this.actionClick.emit(action);\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public_api';\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { input, output, inject, ElementRef, signal, effect, untracked, ChangeDetectionStrategy, ViewEncapsulation, Component } from '@angular/core';
|
|
3
|
+
|
|
4
|
+
class NeuSplitterComponent {
|
|
5
|
+
direction = input('horizontal', ...(ngDevMode ? [{ debugName: "direction" }] : /* istanbul ignore next */ []));
|
|
6
|
+
panes = input([], ...(ngDevMode ? [{ debugName: "panes" }] : /* istanbul ignore next */ []));
|
|
7
|
+
sizeChange = output();
|
|
8
|
+
_el = inject((ElementRef));
|
|
9
|
+
_sizes = signal([], ...(ngDevMode ? [{ debugName: "_sizes" }] : /* istanbul ignore next */ []));
|
|
10
|
+
constructor() {
|
|
11
|
+
effect(() => {
|
|
12
|
+
const ps = this.panes();
|
|
13
|
+
untracked(() => {
|
|
14
|
+
if (!ps.length)
|
|
15
|
+
return;
|
|
16
|
+
const defined = ps.filter((p) => p.size !== undefined);
|
|
17
|
+
const total = defined.reduce((sum, p) => sum + (p.size ?? 0), 0);
|
|
18
|
+
if (defined.length === ps.length) {
|
|
19
|
+
this._sizes.set(ps.map((p) => p.size ?? 0));
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
const remaining = (100 - total) / (ps.length - defined.length);
|
|
23
|
+
this._sizes.set(ps.map((p) => p.size ?? remaining));
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
_dragIndex = -1;
|
|
29
|
+
_dragPos = 0;
|
|
30
|
+
_startDrag(e, index) {
|
|
31
|
+
e.preventDefault();
|
|
32
|
+
this._dragIndex = index;
|
|
33
|
+
this._dragPos = this.direction() === 'horizontal' ? e.clientX : e.clientY;
|
|
34
|
+
const onMove = (ev) => this._onDragMove(ev.clientX, ev.clientY);
|
|
35
|
+
const onUp = () => {
|
|
36
|
+
window.removeEventListener('mousemove', onMove);
|
|
37
|
+
window.removeEventListener('mouseup', onUp);
|
|
38
|
+
this._dragIndex = -1;
|
|
39
|
+
this.sizeChange.emit(this._sizes());
|
|
40
|
+
};
|
|
41
|
+
window.addEventListener('mousemove', onMove);
|
|
42
|
+
window.addEventListener('mouseup', onUp);
|
|
43
|
+
}
|
|
44
|
+
_startTouchDrag(e, index) {
|
|
45
|
+
const t = e.touches[0];
|
|
46
|
+
this._dragIndex = index;
|
|
47
|
+
this._dragPos = this.direction() === 'horizontal' ? t.clientX : t.clientY;
|
|
48
|
+
const onMove = (ev) => this._onDragMove(ev.touches[0].clientX, ev.touches[0].clientY);
|
|
49
|
+
const onEnd = () => {
|
|
50
|
+
window.removeEventListener('touchmove', onMove);
|
|
51
|
+
window.removeEventListener('touchend', onEnd);
|
|
52
|
+
this._dragIndex = -1;
|
|
53
|
+
this.sizeChange.emit(this._sizes());
|
|
54
|
+
};
|
|
55
|
+
window.addEventListener('touchmove', onMove, { passive: true });
|
|
56
|
+
window.addEventListener('touchend', onEnd);
|
|
57
|
+
}
|
|
58
|
+
_onHandleKey(e, index) {
|
|
59
|
+
const step = 2;
|
|
60
|
+
if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') {
|
|
61
|
+
e.preventDefault();
|
|
62
|
+
this._adjustPair(index, -step);
|
|
63
|
+
}
|
|
64
|
+
else if (e.key === 'ArrowRight' || e.key === 'ArrowDown') {
|
|
65
|
+
e.preventDefault();
|
|
66
|
+
this._adjustPair(index, step);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
_onDragMove(clientX, clientY) {
|
|
70
|
+
if (this._dragIndex < 0)
|
|
71
|
+
return;
|
|
72
|
+
const pos = this.direction() === 'horizontal' ? clientX : clientY;
|
|
73
|
+
const delta = pos - this._dragPos;
|
|
74
|
+
this._dragPos = pos;
|
|
75
|
+
const container = this._el.nativeElement;
|
|
76
|
+
const total = this.direction() === 'horizontal' ? container.offsetWidth : container.offsetHeight;
|
|
77
|
+
if (total === 0)
|
|
78
|
+
return;
|
|
79
|
+
this._adjustPair(this._dragIndex, (delta / total) * 100);
|
|
80
|
+
}
|
|
81
|
+
_adjustPair(index, delta) {
|
|
82
|
+
const sizes = [...this._sizes()];
|
|
83
|
+
const container = this._el.nativeElement;
|
|
84
|
+
const total = this.direction() === 'horizontal' ? container.offsetWidth : container.offsetHeight;
|
|
85
|
+
const minA = this.panes()[index]?.min ?? 0;
|
|
86
|
+
const minB = this.panes()[index + 1]?.min ?? 0;
|
|
87
|
+
const minPctA = total > 0 ? (minA / total) * 100 : 0;
|
|
88
|
+
const minPctB = total > 0 ? (minB / total) * 100 : 0;
|
|
89
|
+
let newA = sizes[index] + delta;
|
|
90
|
+
let newB = sizes[index + 1] - delta;
|
|
91
|
+
if (newA < minPctA) {
|
|
92
|
+
newB -= minPctA - newA;
|
|
93
|
+
newA = minPctA;
|
|
94
|
+
}
|
|
95
|
+
if (newB < minPctB) {
|
|
96
|
+
newA -= minPctB - newB;
|
|
97
|
+
newB = minPctB;
|
|
98
|
+
}
|
|
99
|
+
sizes[index] = Math.max(0, newA);
|
|
100
|
+
sizes[index + 1] = Math.max(0, newB);
|
|
101
|
+
this._sizes.set(sizes);
|
|
102
|
+
}
|
|
103
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: NeuSplitterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
104
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: NeuSplitterComponent, isStandalone: true, selector: "neu-splitter", inputs: { direction: { classPropertyName: "direction", publicName: "direction", isSignal: true, isRequired: false, transformFunction: null }, panes: { classPropertyName: "panes", publicName: "panes", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { sizeChange: "sizeChange" }, host: { properties: { "class.neu-splitter--horizontal": "direction() === \"horizontal\"", "class.neu-splitter--vertical": "direction() === \"vertical\"" }, classAttribute: "neu-splitter" }, ngImport: i0, template: `
|
|
105
|
+
@for (size of _sizes(); track $index) {
|
|
106
|
+
<div
|
|
107
|
+
class="neu-splitter__pane"
|
|
108
|
+
[style.flex-basis]="size + '%'"
|
|
109
|
+
[style.min-width]="direction() === 'horizontal' ? (panes()[$index]?.min ?? 0) + 'px' : null"
|
|
110
|
+
[style.min-height]="direction() === 'vertical' ? (panes()[$index]?.min ?? 0) + 'px' : null"
|
|
111
|
+
>
|
|
112
|
+
<ng-content select="neu-splitter-pane" />
|
|
113
|
+
</div>
|
|
114
|
+
@if (!$last) {
|
|
115
|
+
<div
|
|
116
|
+
class="neu-splitter__handle"
|
|
117
|
+
role="separator"
|
|
118
|
+
tabindex="0"
|
|
119
|
+
[attr.aria-valuenow]="size"
|
|
120
|
+
[attr.aria-valuemin]="0"
|
|
121
|
+
[attr.aria-valuemax]="100"
|
|
122
|
+
[attr.aria-label]="'Separador ' + ($index + 1)"
|
|
123
|
+
(mousedown)="_startDrag($event, $index)"
|
|
124
|
+
(touchstart)="_startTouchDrag($event, $index)"
|
|
125
|
+
(keydown)="_onHandleKey($event, $index)"
|
|
126
|
+
>
|
|
127
|
+
<span class="neu-splitter__handle-dots" aria-hidden="true"></span>
|
|
128
|
+
</div>
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
`, isInline: true, styles: ["@charset \"UTF-8\";.neu-splitter{display:flex;overflow:hidden;width:100%;height:100%}.neu-splitter--horizontal{flex-direction:row}.neu-splitter--vertical{flex-direction:column}.neu-splitter__pane{overflow:auto;flex-shrink:0}.neu-splitter__handle{flex-shrink:0;display:flex;align-items:center;justify-content:center;background:var(--neu-border-color, #e5e7eb);transition:background .15s;cursor:col-resize;position:relative;z-index:1;outline:none}.neu-splitter--horizontal .neu-splitter__handle{width:var(--neu-splitter-handle-size, 4px);cursor:col-resize;min-height:0}.neu-splitter--horizontal .neu-splitter__handle:hover,.neu-splitter--horizontal .neu-splitter__handle:focus-visible{background:var(--neu-color-primary, #0ea5e9);width:4px}.neu-splitter--vertical .neu-splitter__handle{height:var(--neu-splitter-handle-size, 4px);cursor:row-resize;width:100%}.neu-splitter--vertical .neu-splitter__handle:hover,.neu-splitter--vertical .neu-splitter__handle:focus-visible{background:var(--neu-color-primary, #0ea5e9);height:4px}.neu-splitter__handle:focus-visible{outline:2px solid var(--neu-focus-ring, #0ea5e9);outline-offset:1px}.neu-splitter__handle-dots{display:block;width:4px;height:24px;background:repeating-linear-gradient(to bottom,var(--neu-text-secondary, #9ca3af) 0 3px,transparent 3px 6px);border-radius:2px;opacity:.6}.neu-splitter--vertical .neu-splitter__handle-dots{width:24px;height:4px;background:repeating-linear-gradient(to right,var(--neu-text-secondary, #9ca3af) 0 3px,transparent 3px 6px)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
132
|
+
}
|
|
133
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: NeuSplitterComponent, decorators: [{
|
|
134
|
+
type: Component,
|
|
135
|
+
args: [{ selector: 'neu-splitter', imports: [], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
136
|
+
class: 'neu-splitter',
|
|
137
|
+
'[class.neu-splitter--horizontal]': 'direction() === "horizontal"',
|
|
138
|
+
'[class.neu-splitter--vertical]': 'direction() === "vertical"',
|
|
139
|
+
}, template: `
|
|
140
|
+
@for (size of _sizes(); track $index) {
|
|
141
|
+
<div
|
|
142
|
+
class="neu-splitter__pane"
|
|
143
|
+
[style.flex-basis]="size + '%'"
|
|
144
|
+
[style.min-width]="direction() === 'horizontal' ? (panes()[$index]?.min ?? 0) + 'px' : null"
|
|
145
|
+
[style.min-height]="direction() === 'vertical' ? (panes()[$index]?.min ?? 0) + 'px' : null"
|
|
146
|
+
>
|
|
147
|
+
<ng-content select="neu-splitter-pane" />
|
|
148
|
+
</div>
|
|
149
|
+
@if (!$last) {
|
|
150
|
+
<div
|
|
151
|
+
class="neu-splitter__handle"
|
|
152
|
+
role="separator"
|
|
153
|
+
tabindex="0"
|
|
154
|
+
[attr.aria-valuenow]="size"
|
|
155
|
+
[attr.aria-valuemin]="0"
|
|
156
|
+
[attr.aria-valuemax]="100"
|
|
157
|
+
[attr.aria-label]="'Separador ' + ($index + 1)"
|
|
158
|
+
(mousedown)="_startDrag($event, $index)"
|
|
159
|
+
(touchstart)="_startTouchDrag($event, $index)"
|
|
160
|
+
(keydown)="_onHandleKey($event, $index)"
|
|
161
|
+
>
|
|
162
|
+
<span class="neu-splitter__handle-dots" aria-hidden="true"></span>
|
|
163
|
+
</div>
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
`, styles: ["@charset \"UTF-8\";.neu-splitter{display:flex;overflow:hidden;width:100%;height:100%}.neu-splitter--horizontal{flex-direction:row}.neu-splitter--vertical{flex-direction:column}.neu-splitter__pane{overflow:auto;flex-shrink:0}.neu-splitter__handle{flex-shrink:0;display:flex;align-items:center;justify-content:center;background:var(--neu-border-color, #e5e7eb);transition:background .15s;cursor:col-resize;position:relative;z-index:1;outline:none}.neu-splitter--horizontal .neu-splitter__handle{width:var(--neu-splitter-handle-size, 4px);cursor:col-resize;min-height:0}.neu-splitter--horizontal .neu-splitter__handle:hover,.neu-splitter--horizontal .neu-splitter__handle:focus-visible{background:var(--neu-color-primary, #0ea5e9);width:4px}.neu-splitter--vertical .neu-splitter__handle{height:var(--neu-splitter-handle-size, 4px);cursor:row-resize;width:100%}.neu-splitter--vertical .neu-splitter__handle:hover,.neu-splitter--vertical .neu-splitter__handle:focus-visible{background:var(--neu-color-primary, #0ea5e9);height:4px}.neu-splitter__handle:focus-visible{outline:2px solid var(--neu-focus-ring, #0ea5e9);outline-offset:1px}.neu-splitter__handle-dots{display:block;width:4px;height:24px;background:repeating-linear-gradient(to bottom,var(--neu-text-secondary, #9ca3af) 0 3px,transparent 3px 6px);border-radius:2px;opacity:.6}.neu-splitter--vertical .neu-splitter__handle-dots{width:24px;height:4px;background:repeating-linear-gradient(to right,var(--neu-text-secondary, #9ca3af) 0 3px,transparent 3px 6px)}\n"] }]
|
|
167
|
+
}], ctorParameters: () => [], propDecorators: { direction: [{ type: i0.Input, args: [{ isSignal: true, alias: "direction", required: false }] }], panes: [{ type: i0.Input, args: [{ isSignal: true, alias: "panes", required: false }] }], sizeChange: [{ type: i0.Output, args: ["sizeChange"] }] } });
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Generated bundle index. Do not edit.
|
|
171
|
+
*/
|
|
172
|
+
|
|
173
|
+
export { NeuSplitterComponent };
|
|
174
|
+
//# sourceMappingURL=neural-ui-core-splitter.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"neural-ui-core-splitter.mjs","sources":["../../../../projects/ui-core/splitter/neu-splitter.component.ts","../../../../projects/ui-core/splitter/neural-ui-core-splitter.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n ViewEncapsulation,\n effect,\n inject,\n input,\n output,\n signal,\n untracked,\n} from '@angular/core';\n\nexport type NeuSplitterDirection = 'horizontal' | 'vertical';\n\nexport interface NeuSplitterPane {\n size?: number;\n min?: number;\n max?: number;\n}\n\n@Component({\n selector: 'neu-splitter',\n imports: [],\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n class: 'neu-splitter',\n '[class.neu-splitter--horizontal]': 'direction() === \"horizontal\"',\n '[class.neu-splitter--vertical]': 'direction() === \"vertical\"',\n },\n template: `\n @for (size of _sizes(); track $index) {\n <div\n class=\"neu-splitter__pane\"\n [style.flex-basis]=\"size + '%'\"\n [style.min-width]=\"direction() === 'horizontal' ? (panes()[$index]?.min ?? 0) + 'px' : null\"\n [style.min-height]=\"direction() === 'vertical' ? (panes()[$index]?.min ?? 0) + 'px' : null\"\n >\n <ng-content select=\"neu-splitter-pane\" />\n </div>\n @if (!$last) {\n <div\n class=\"neu-splitter__handle\"\n role=\"separator\"\n tabindex=\"0\"\n [attr.aria-valuenow]=\"size\"\n [attr.aria-valuemin]=\"0\"\n [attr.aria-valuemax]=\"100\"\n [attr.aria-label]=\"'Separador ' + ($index + 1)\"\n (mousedown)=\"_startDrag($event, $index)\"\n (touchstart)=\"_startTouchDrag($event, $index)\"\n (keydown)=\"_onHandleKey($event, $index)\"\n >\n <span class=\"neu-splitter__handle-dots\" aria-hidden=\"true\"></span>\n </div>\n }\n }\n `,\n styleUrl: './neu-splitter.component.scss',\n})\nexport class NeuSplitterComponent {\n readonly direction = input<NeuSplitterDirection>('horizontal');\n readonly panes = input<NeuSplitterPane[]>([]);\n readonly sizeChange = output<number[]>();\n\n private readonly _el = inject(ElementRef<HTMLElement>);\n readonly _sizes = signal<number[]>([]);\n\n constructor() {\n effect(() => {\n const ps = this.panes();\n untracked(() => {\n if (!ps.length) return;\n const defined = ps.filter((p) => p.size !== undefined);\n const total = defined.reduce((sum, p) => sum + (p.size ?? 0), 0);\n if (defined.length === ps.length) {\n this._sizes.set(ps.map((p) => p.size ?? 0));\n } else {\n const remaining = (100 - total) / (ps.length - defined.length);\n this._sizes.set(ps.map((p) => p.size ?? remaining));\n }\n });\n });\n }\n\n private _dragIndex = -1;\n private _dragPos = 0;\n\n _startDrag(e: MouseEvent, index: number): void {\n e.preventDefault();\n this._dragIndex = index;\n this._dragPos = this.direction() === 'horizontal' ? e.clientX : e.clientY;\n const onMove = (ev: MouseEvent) => this._onDragMove(ev.clientX, ev.clientY);\n const onUp = () => {\n window.removeEventListener('mousemove', onMove);\n window.removeEventListener('mouseup', onUp);\n this._dragIndex = -1;\n this.sizeChange.emit(this._sizes());\n };\n window.addEventListener('mousemove', onMove);\n window.addEventListener('mouseup', onUp);\n }\n\n _startTouchDrag(e: TouchEvent, index: number): void {\n const t = e.touches[0];\n this._dragIndex = index;\n this._dragPos = this.direction() === 'horizontal' ? t.clientX : t.clientY;\n const onMove = (ev: TouchEvent) =>\n this._onDragMove(ev.touches[0].clientX, ev.touches[0].clientY);\n const onEnd = () => {\n window.removeEventListener('touchmove', onMove);\n window.removeEventListener('touchend', onEnd);\n this._dragIndex = -1;\n this.sizeChange.emit(this._sizes());\n };\n window.addEventListener('touchmove', onMove, { passive: true });\n window.addEventListener('touchend', onEnd);\n }\n\n _onHandleKey(e: KeyboardEvent, index: number): void {\n const step = 2;\n if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') {\n e.preventDefault();\n this._adjustPair(index, -step);\n } else if (e.key === 'ArrowRight' || e.key === 'ArrowDown') {\n e.preventDefault();\n this._adjustPair(index, step);\n }\n }\n\n private _onDragMove(clientX: number, clientY: number): void {\n if (this._dragIndex < 0) return;\n const pos = this.direction() === 'horizontal' ? clientX : clientY;\n const delta = pos - this._dragPos;\n this._dragPos = pos;\n const container = this._el.nativeElement;\n const total =\n this.direction() === 'horizontal' ? container.offsetWidth : container.offsetHeight;\n if (total === 0) return;\n this._adjustPair(this._dragIndex, (delta / total) * 100);\n }\n\n private _adjustPair(index: number, delta: number): void {\n const sizes = [...this._sizes()];\n const container = this._el.nativeElement;\n const total =\n this.direction() === 'horizontal' ? container.offsetWidth : container.offsetHeight;\n const minA = this.panes()[index]?.min ?? 0;\n const minB = this.panes()[index + 1]?.min ?? 0;\n const minPctA = total > 0 ? (minA / total) * 100 : 0;\n const minPctB = total > 0 ? (minB / total) * 100 : 0;\n\n let newA = sizes[index] + delta;\n let newB = sizes[index + 1] - delta;\n if (newA < minPctA) {\n newB -= minPctA - newA;\n newA = minPctA;\n }\n if (newB < minPctB) {\n newA -= minPctB - newB;\n newB = minPctB;\n }\n\n sizes[index] = Math.max(0, newA);\n sizes[index + 1] = Math.max(0, newB);\n this._sizes.set(sizes);\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public_api';\n"],"names":[],"mappings":";;;MA6Da,oBAAoB,CAAA;AACtB,IAAA,SAAS,GAAG,KAAK,CAAuB,YAAY,gFAAC;AACrD,IAAA,KAAK,GAAG,KAAK,CAAoB,EAAE,4EAAC;IACpC,UAAU,GAAG,MAAM,EAAY;AAEvB,IAAA,GAAG,GAAG,MAAM,EAAC,UAAuB,EAAC;AAC7C,IAAA,MAAM,GAAG,MAAM,CAAW,EAAE,6EAAC;AAEtC,IAAA,WAAA,GAAA;QACE,MAAM,CAAC,MAAK;AACV,YAAA,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE;YACvB,SAAS,CAAC,MAAK;gBACb,IAAI,CAAC,EAAE,CAAC,MAAM;oBAAE;AAChB,gBAAA,MAAM,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC;gBACtD,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC;gBAChE,IAAI,OAAO,CAAC,MAAM,KAAK,EAAE,CAAC,MAAM,EAAE;oBAChC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;gBAC7C;qBAAO;AACL,oBAAA,MAAM,SAAS,GAAG,CAAC,GAAG,GAAG,KAAK,KAAK,EAAE,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;oBAC9D,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,IAAI,SAAS,CAAC,CAAC;gBACrD;AACF,YAAA,CAAC,CAAC;AACJ,QAAA,CAAC,CAAC;IACJ;IAEQ,UAAU,GAAG,CAAC,CAAC;IACf,QAAQ,GAAG,CAAC;IAEpB,UAAU,CAAC,CAAa,EAAE,KAAa,EAAA;QACrC,CAAC,CAAC,cAAc,EAAE;AAClB,QAAA,IAAI,CAAC,UAAU,GAAG,KAAK;QACvB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,SAAS,EAAE,KAAK,YAAY,GAAG,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO;AACzE,QAAA,MAAM,MAAM,GAAG,CAAC,EAAc,KAAK,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC;QAC3E,MAAM,IAAI,GAAG,MAAK;AAChB,YAAA,MAAM,CAAC,mBAAmB,CAAC,WAAW,EAAE,MAAM,CAAC;AAC/C,YAAA,MAAM,CAAC,mBAAmB,CAAC,SAAS,EAAE,IAAI,CAAC;AAC3C,YAAA,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;YACpB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;AACrC,QAAA,CAAC;AACD,QAAA,MAAM,CAAC,gBAAgB,CAAC,WAAW,EAAE,MAAM,CAAC;AAC5C,QAAA,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAAC;IAC1C;IAEA,eAAe,CAAC,CAAa,EAAE,KAAa,EAAA;QAC1C,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;AACtB,QAAA,IAAI,CAAC,UAAU,GAAG,KAAK;QACvB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,SAAS,EAAE,KAAK,YAAY,GAAG,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO;AACzE,QAAA,MAAM,MAAM,GAAG,CAAC,EAAc,KAC5B,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;QAChE,MAAM,KAAK,GAAG,MAAK;AACjB,YAAA,MAAM,CAAC,mBAAmB,CAAC,WAAW,EAAE,MAAM,CAAC;AAC/C,YAAA,MAAM,CAAC,mBAAmB,CAAC,UAAU,EAAE,KAAK,CAAC;AAC7C,YAAA,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;YACpB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;AACrC,QAAA,CAAC;AACD,QAAA,MAAM,CAAC,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC/D,QAAA,MAAM,CAAC,gBAAgB,CAAC,UAAU,EAAE,KAAK,CAAC;IAC5C;IAEA,YAAY,CAAC,CAAgB,EAAE,KAAa,EAAA;QAC1C,MAAM,IAAI,GAAG,CAAC;AACd,QAAA,IAAI,CAAC,CAAC,GAAG,KAAK,WAAW,IAAI,CAAC,CAAC,GAAG,KAAK,SAAS,EAAE;YAChD,CAAC,CAAC,cAAc,EAAE;YAClB,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC;QAChC;AAAO,aAAA,IAAI,CAAC,CAAC,GAAG,KAAK,YAAY,IAAI,CAAC,CAAC,GAAG,KAAK,WAAW,EAAE;YAC1D,CAAC,CAAC,cAAc,EAAE;AAClB,YAAA,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC;QAC/B;IACF;IAEQ,WAAW,CAAC,OAAe,EAAE,OAAe,EAAA;AAClD,QAAA,IAAI,IAAI,CAAC,UAAU,GAAG,CAAC;YAAE;AACzB,QAAA,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,EAAE,KAAK,YAAY,GAAG,OAAO,GAAG,OAAO;AACjE,QAAA,MAAM,KAAK,GAAG,GAAG,GAAG,IAAI,CAAC,QAAQ;AACjC,QAAA,IAAI,CAAC,QAAQ,GAAG,GAAG;AACnB,QAAA,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,aAAa;QACxC,MAAM,KAAK,GACT,IAAI,CAAC,SAAS,EAAE,KAAK,YAAY,GAAG,SAAS,CAAC,WAAW,GAAG,SAAS,CAAC,YAAY;QACpF,IAAI,KAAK,KAAK,CAAC;YAAE;AACjB,QAAA,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,KAAK,GAAG,KAAK,IAAI,GAAG,CAAC;IAC1D;IAEQ,WAAW,CAAC,KAAa,EAAE,KAAa,EAAA;QAC9C,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;AAChC,QAAA,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,aAAa;QACxC,MAAM,KAAK,GACT,IAAI,CAAC,SAAS,EAAE,KAAK,YAAY,GAAG,SAAS,CAAC,WAAW,GAAG,SAAS,CAAC,YAAY;AACpF,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC;AAC1C,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,GAAG,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC;AAC9C,QAAA,MAAM,OAAO,GAAG,KAAK,GAAG,CAAC,GAAG,CAAC,IAAI,GAAG,KAAK,IAAI,GAAG,GAAG,CAAC;AACpD,QAAA,MAAM,OAAO,GAAG,KAAK,GAAG,CAAC,GAAG,CAAC,IAAI,GAAG,KAAK,IAAI,GAAG,GAAG,CAAC;QAEpD,IAAI,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,KAAK;QAC/B,IAAI,IAAI,GAAG,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,KAAK;AACnC,QAAA,IAAI,IAAI,GAAG,OAAO,EAAE;AAClB,YAAA,IAAI,IAAI,OAAO,GAAG,IAAI;YACtB,IAAI,GAAG,OAAO;QAChB;AACA,QAAA,IAAI,IAAI,GAAG,OAAO,EAAE;AAClB,YAAA,IAAI,IAAI,OAAO,GAAG,IAAI;YACtB,IAAI,GAAG,OAAO;QAChB;AAEA,QAAA,KAAK,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC;AAChC,QAAA,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC;AACpC,QAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC;IACxB;uGA1GW,oBAAoB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAApB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,oBAAoB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,cAAA,EAAA,MAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,KAAA,EAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,UAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,UAAA,EAAA,YAAA,EAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,gCAAA,EAAA,gCAAA,EAAA,8BAAA,EAAA,8BAAA,EAAA,EAAA,cAAA,EAAA,cAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EA9BrB;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,2+CAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,aAAA,EAAA,EAAA,CAAA,iBAAA,CAAA,IAAA,EAAA,CAAA;;2FAGU,oBAAoB,EAAA,UAAA,EAAA,CAAA;kBAxChC,SAAS;+BACE,cAAc,EAAA,OAAA,EACf,EAAE,EAAA,aAAA,EACI,iBAAiB,CAAC,IAAI,EAAA,eAAA,EACpB,uBAAuB,CAAC,MAAM,EAAA,IAAA,EACzC;AACJ,wBAAA,KAAK,EAAE,cAAc;AACrB,wBAAA,kCAAkC,EAAE,8BAA8B;AAClE,wBAAA,gCAAgC,EAAE,4BAA4B;qBAC/D,EAAA,QAAA,EACS;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,2+CAAA,CAAA,EAAA;;;AC1DH;;AAEG;;;;"}
|