@neural-ui/core 1.2.1 → 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.
Files changed (239) hide show
  1. package/README.md +56 -88
  2. package/accordion/package.json +4 -0
  3. package/alert/package.json +4 -0
  4. package/autocomplete/package.json +4 -0
  5. package/avatar/package.json +4 -0
  6. package/badge/package.json +4 -0
  7. package/block-ui/package.json +4 -0
  8. package/breadcrumb/package.json +4 -0
  9. package/button/package.json +4 -0
  10. package/card/package.json +4 -0
  11. package/chart/package.json +4 -0
  12. package/checkbox/package.json +4 -0
  13. package/chip/package.json +4 -0
  14. package/code-block/package.json +4 -0
  15. package/color-picker/package.json +4 -0
  16. package/command-palette/package.json +4 -0
  17. package/confirm-dialog/package.json +4 -0
  18. package/context-menu/package.json +4 -0
  19. package/dashboard-grid/package.json +4 -0
  20. package/date-input/package.json +4 -0
  21. package/divider/package.json +4 -0
  22. package/empty-state/package.json +4 -0
  23. package/fesm2022/neural-ui-core-accordion.mjs +162 -0
  24. package/fesm2022/neural-ui-core-accordion.mjs.map +1 -0
  25. package/fesm2022/neural-ui-core-alert.mjs +116 -0
  26. package/fesm2022/neural-ui-core-alert.mjs.map +1 -0
  27. package/fesm2022/neural-ui-core-autocomplete.mjs +332 -0
  28. package/fesm2022/neural-ui-core-autocomplete.mjs.map +1 -0
  29. package/fesm2022/neural-ui-core-avatar.mjs +109 -0
  30. package/fesm2022/neural-ui-core-avatar.mjs.map +1 -0
  31. package/fesm2022/neural-ui-core-badge.mjs +54 -0
  32. package/fesm2022/neural-ui-core-badge.mjs.map +1 -0
  33. package/fesm2022/neural-ui-core-block-ui.mjs +95 -0
  34. package/fesm2022/neural-ui-core-block-ui.mjs.map +1 -0
  35. package/fesm2022/neural-ui-core-breadcrumb.mjs +84 -0
  36. package/fesm2022/neural-ui-core-breadcrumb.mjs.map +1 -0
  37. package/fesm2022/neural-ui-core-button.mjs +125 -0
  38. package/fesm2022/neural-ui-core-button.mjs.map +1 -0
  39. package/fesm2022/neural-ui-core-card.mjs +69 -0
  40. package/fesm2022/neural-ui-core-card.mjs.map +1 -0
  41. package/fesm2022/neural-ui-core-chart.mjs +287 -0
  42. package/fesm2022/neural-ui-core-chart.mjs.map +1 -0
  43. package/fesm2022/neural-ui-core-checkbox.mjs +138 -0
  44. package/fesm2022/neural-ui-core-checkbox.mjs.map +1 -0
  45. package/fesm2022/neural-ui-core-chip.mjs +130 -0
  46. package/fesm2022/neural-ui-core-chip.mjs.map +1 -0
  47. package/fesm2022/neural-ui-core-code-block.mjs +250 -0
  48. package/fesm2022/neural-ui-core-code-block.mjs.map +1 -0
  49. package/fesm2022/neural-ui-core-color-picker.mjs +435 -0
  50. package/fesm2022/neural-ui-core-color-picker.mjs.map +1 -0
  51. package/fesm2022/neural-ui-core-command-palette.mjs +235 -0
  52. package/fesm2022/neural-ui-core-command-palette.mjs.map +1 -0
  53. package/fesm2022/neural-ui-core-confirm-dialog.mjs +118 -0
  54. package/fesm2022/neural-ui-core-confirm-dialog.mjs.map +1 -0
  55. package/fesm2022/neural-ui-core-context-menu.mjs +158 -0
  56. package/fesm2022/neural-ui-core-context-menu.mjs.map +1 -0
  57. package/fesm2022/neural-ui-core-dashboard-grid.mjs +144 -0
  58. package/fesm2022/neural-ui-core-dashboard-grid.mjs.map +1 -0
  59. package/fesm2022/neural-ui-core-date-input.mjs +1332 -0
  60. package/fesm2022/neural-ui-core-date-input.mjs.map +1 -0
  61. package/fesm2022/neural-ui-core-divider.mjs +54 -0
  62. package/fesm2022/neural-ui-core-divider.mjs.map +1 -0
  63. package/fesm2022/neural-ui-core-empty-state.mjs +84 -0
  64. package/fesm2022/neural-ui-core-empty-state.mjs.map +1 -0
  65. package/fesm2022/neural-ui-core-filter-bar.mjs +118 -0
  66. package/fesm2022/neural-ui-core-filter-bar.mjs.map +1 -0
  67. package/fesm2022/neural-ui-core-icon.mjs +50 -0
  68. package/fesm2022/neural-ui-core-icon.mjs.map +1 -0
  69. package/fesm2022/neural-ui-core-image-viewer.mjs +309 -0
  70. package/fesm2022/neural-ui-core-image-viewer.mjs.map +1 -0
  71. package/fesm2022/neural-ui-core-input-otp.mjs +192 -0
  72. package/fesm2022/neural-ui-core-input-otp.mjs.map +1 -0
  73. package/fesm2022/neural-ui-core-input.mjs +320 -0
  74. package/fesm2022/neural-ui-core-input.mjs.map +1 -0
  75. package/fesm2022/neural-ui-core-knob.mjs +323 -0
  76. package/fesm2022/neural-ui-core-knob.mjs.map +1 -0
  77. package/fesm2022/neural-ui-core-meter-group.mjs +122 -0
  78. package/fesm2022/neural-ui-core-meter-group.mjs.map +1 -0
  79. package/fesm2022/neural-ui-core-modal.mjs +156 -0
  80. package/fesm2022/neural-ui-core-modal.mjs.map +1 -0
  81. package/fesm2022/neural-ui-core-multiselect.mjs +748 -0
  82. package/fesm2022/neural-ui-core-multiselect.mjs.map +1 -0
  83. package/fesm2022/neural-ui-core-nav.mjs +952 -0
  84. package/fesm2022/neural-ui-core-nav.mjs.map +1 -0
  85. package/fesm2022/neural-ui-core-notification-center.mjs +264 -0
  86. package/fesm2022/neural-ui-core-notification-center.mjs.map +1 -0
  87. package/fesm2022/neural-ui-core-number-input.mjs +331 -0
  88. package/fesm2022/neural-ui-core-number-input.mjs.map +1 -0
  89. package/fesm2022/neural-ui-core-pagination.mjs +198 -0
  90. package/fesm2022/neural-ui-core-pagination.mjs.map +1 -0
  91. package/fesm2022/neural-ui-core-popover.mjs +207 -0
  92. package/fesm2022/neural-ui-core-popover.mjs.map +1 -0
  93. package/fesm2022/neural-ui-core-progress-bar.mjs +105 -0
  94. package/fesm2022/neural-ui-core-progress-bar.mjs.map +1 -0
  95. package/fesm2022/neural-ui-core-radio.mjs +171 -0
  96. package/fesm2022/neural-ui-core-radio.mjs.map +1 -0
  97. package/fesm2022/neural-ui-core-rating.mjs +151 -0
  98. package/fesm2022/neural-ui-core-rating.mjs.map +1 -0
  99. package/fesm2022/neural-ui-core-select.mjs +638 -0
  100. package/fesm2022/neural-ui-core-select.mjs.map +1 -0
  101. package/fesm2022/neural-ui-core-sidebar.mjs +214 -0
  102. package/fesm2022/neural-ui-core-sidebar.mjs.map +1 -0
  103. package/fesm2022/neural-ui-core-skeleton.mjs +40 -0
  104. package/fesm2022/neural-ui-core-skeleton.mjs.map +1 -0
  105. package/fesm2022/neural-ui-core-slider.mjs +146 -0
  106. package/fesm2022/neural-ui-core-slider.mjs.map +1 -0
  107. package/fesm2022/neural-ui-core-spinner.mjs +113 -0
  108. package/fesm2022/neural-ui-core-spinner.mjs.map +1 -0
  109. package/fesm2022/neural-ui-core-split-button.mjs +252 -0
  110. package/fesm2022/neural-ui-core-split-button.mjs.map +1 -0
  111. package/fesm2022/neural-ui-core-splitter.mjs +174 -0
  112. package/fesm2022/neural-ui-core-splitter.mjs.map +1 -0
  113. package/fesm2022/neural-ui-core-stats-card.mjs +163 -0
  114. package/fesm2022/neural-ui-core-stats-card.mjs.map +1 -0
  115. package/fesm2022/neural-ui-core-stepper.mjs +204 -0
  116. package/fesm2022/neural-ui-core-stepper.mjs.map +1 -0
  117. package/fesm2022/neural-ui-core-switch.mjs +111 -0
  118. package/fesm2022/neural-ui-core-switch.mjs.map +1 -0
  119. package/fesm2022/neural-ui-core-table.mjs +1860 -0
  120. package/fesm2022/neural-ui-core-table.mjs.map +1 -0
  121. package/fesm2022/neural-ui-core-tabs.mjs +246 -0
  122. package/fesm2022/neural-ui-core-tabs.mjs.map +1 -0
  123. package/fesm2022/neural-ui-core-textarea.mjs +188 -0
  124. package/fesm2022/neural-ui-core-textarea.mjs.map +1 -0
  125. package/fesm2022/neural-ui-core-timeline.mjs +117 -0
  126. package/fesm2022/neural-ui-core-timeline.mjs.map +1 -0
  127. package/fesm2022/neural-ui-core-toast.mjs +171 -0
  128. package/fesm2022/neural-ui-core-toast.mjs.map +1 -0
  129. package/fesm2022/neural-ui-core-toggle-button-group.mjs +162 -0
  130. package/fesm2022/neural-ui-core-toggle-button-group.mjs.map +1 -0
  131. package/fesm2022/neural-ui-core-toolbar.mjs +67 -0
  132. package/fesm2022/neural-ui-core-toolbar.mjs.map +1 -0
  133. package/fesm2022/neural-ui-core-tooltip.mjs +151 -0
  134. package/fesm2022/neural-ui-core-tooltip.mjs.map +1 -0
  135. package/fesm2022/neural-ui-core-url-state.mjs +96 -0
  136. package/fesm2022/neural-ui-core-url-state.mjs.map +1 -0
  137. package/fesm2022/neural-ui-core-virtual-list.mjs +126 -0
  138. package/fesm2022/neural-ui-core-virtual-list.mjs.map +1 -0
  139. package/fesm2022/neural-ui-core.mjs +11 -8544
  140. package/fesm2022/neural-ui-core.mjs.map +1 -1
  141. package/filter-bar/package.json +4 -0
  142. package/icon/package.json +4 -0
  143. package/image-viewer/package.json +4 -0
  144. package/input/package.json +4 -0
  145. package/input-otp/package.json +4 -0
  146. package/knob/package.json +4 -0
  147. package/meter-group/package.json +4 -0
  148. package/modal/package.json +4 -0
  149. package/multiselect/package.json +4 -0
  150. package/nav/package.json +4 -0
  151. package/notification-center/package.json +4 -0
  152. package/number-input/package.json +4 -0
  153. package/package.json +252 -5
  154. package/pagination/package.json +4 -0
  155. package/popover/package.json +4 -0
  156. package/progress-bar/package.json +4 -0
  157. package/radio/package.json +4 -0
  158. package/rating/package.json +4 -0
  159. package/select/package.json +4 -0
  160. package/sidebar/package.json +4 -0
  161. package/skeleton/package.json +4 -0
  162. package/slider/package.json +4 -0
  163. package/spinner/package.json +4 -0
  164. package/split-button/package.json +4 -0
  165. package/splitter/package.json +4 -0
  166. package/stats-card/package.json +4 -0
  167. package/stepper/package.json +4 -0
  168. package/styles/_tokens.scss +202 -0
  169. package/styles.scss +1 -0
  170. package/switch/package.json +4 -0
  171. package/table/package.json +4 -0
  172. package/tabs/package.json +4 -0
  173. package/textarea/package.json +4 -0
  174. package/timeline/package.json +4 -0
  175. package/toast/package.json +4 -0
  176. package/toggle-button-group/package.json +4 -0
  177. package/toolbar/package.json +4 -0
  178. package/tooltip/package.json +4 -0
  179. package/types/neural-ui-core-accordion.d.ts +55 -0
  180. package/types/neural-ui-core-alert.d.ts +47 -0
  181. package/types/neural-ui-core-autocomplete.d.ts +69 -0
  182. package/types/neural-ui-core-avatar.d.ts +39 -0
  183. package/types/neural-ui-core-badge.d.ts +36 -0
  184. package/types/neural-ui-core-block-ui.d.ts +46 -0
  185. package/types/neural-ui-core-breadcrumb.d.ts +38 -0
  186. package/types/neural-ui-core-button.d.ts +55 -0
  187. package/types/neural-ui-core-card.d.ts +37 -0
  188. package/types/neural-ui-core-chart.d.ts +236 -0
  189. package/types/neural-ui-core-checkbox.d.ts +33 -0
  190. package/types/neural-ui-core-chip.d.ts +53 -0
  191. package/types/neural-ui-core-code-block.d.ts +55 -0
  192. package/types/neural-ui-core-color-picker.d.ts +55 -0
  193. package/types/neural-ui-core-command-palette.d.ts +56 -0
  194. package/types/neural-ui-core-confirm-dialog.d.ts +50 -0
  195. package/types/neural-ui-core-context-menu.d.ts +66 -0
  196. package/types/neural-ui-core-dashboard-grid.d.ts +41 -0
  197. package/types/neural-ui-core-date-input.d.ts +178 -0
  198. package/types/neural-ui-core-divider.d.ts +20 -0
  199. package/types/neural-ui-core-empty-state.d.ts +32 -0
  200. package/types/neural-ui-core-filter-bar.d.ts +49 -0
  201. package/types/neural-ui-core-icon.d.ts +33 -0
  202. package/types/neural-ui-core-image-viewer.d.ts +67 -0
  203. package/types/neural-ui-core-input-otp.d.ts +49 -0
  204. package/types/neural-ui-core-input.d.ts +86 -0
  205. package/types/neural-ui-core-knob.d.ts +68 -0
  206. package/types/neural-ui-core-meter-group.d.ts +52 -0
  207. package/types/neural-ui-core-modal.d.ts +54 -0
  208. package/types/neural-ui-core-multiselect.d.ts +129 -0
  209. package/types/neural-ui-core-nav.d.ts +69 -0
  210. package/types/neural-ui-core-notification-center.d.ts +60 -0
  211. package/types/neural-ui-core-number-input.d.ts +63 -0
  212. package/types/neural-ui-core-pagination.d.ts +30 -0
  213. package/types/neural-ui-core-popover.d.ts +73 -0
  214. package/types/neural-ui-core-progress-bar.d.ts +35 -0
  215. package/types/neural-ui-core-radio.d.ts +51 -0
  216. package/types/neural-ui-core-rating.d.ts +34 -0
  217. package/types/neural-ui-core-select.d.ts +161 -0
  218. package/types/neural-ui-core-sidebar.d.ts +57 -0
  219. package/types/neural-ui-core-skeleton.d.ts +22 -0
  220. package/types/neural-ui-core-slider.d.ts +42 -0
  221. package/types/neural-ui-core-spinner.d.ts +38 -0
  222. package/types/neural-ui-core-split-button.d.ts +65 -0
  223. package/types/neural-ui-core-splitter.d.ts +28 -0
  224. package/types/neural-ui-core-stats-card.d.ts +39 -0
  225. package/types/neural-ui-core-stepper.d.ts +51 -0
  226. package/types/neural-ui-core-switch.d.ts +34 -0
  227. package/types/neural-ui-core-table.d.ts +282 -0
  228. package/types/neural-ui-core-tabs.d.ts +76 -0
  229. package/types/neural-ui-core-textarea.d.ts +52 -0
  230. package/types/neural-ui-core-timeline.d.ts +33 -0
  231. package/types/neural-ui-core-toast.d.ts +70 -0
  232. package/types/neural-ui-core-toggle-button-group.d.ts +63 -0
  233. package/types/neural-ui-core-toolbar.d.ts +36 -0
  234. package/types/neural-ui-core-tooltip.d.ts +48 -0
  235. package/types/neural-ui-core-url-state.d.ts +58 -0
  236. package/types/neural-ui-core-virtual-list.d.ts +60 -0
  237. package/types/neural-ui-core.d.ts +3 -2105
  238. package/url-state/package.json +4 -0
  239. 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":"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"}