@ngbase/adk 0.1.17 → 0.1.19

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 (205) hide show
  1. package/fesm2022/ngbase-adk-a11y.mjs +42 -42
  2. package/fesm2022/ngbase-adk-a11y.mjs.map +1 -1
  3. package/fesm2022/ngbase-adk-accordion.mjs +20 -26
  4. package/fesm2022/ngbase-adk-accordion.mjs.map +1 -1
  5. package/fesm2022/ngbase-adk-autocomplete.mjs +11 -11
  6. package/fesm2022/ngbase-adk-autocomplete.mjs.map +1 -1
  7. package/fesm2022/ngbase-adk-avatar.mjs +13 -13
  8. package/fesm2022/ngbase-adk-avatar.mjs.map +1 -1
  9. package/fesm2022/ngbase-adk-bidi.mjs +3 -3
  10. package/fesm2022/ngbase-adk-bidi.mjs.map +1 -1
  11. package/fesm2022/ngbase-adk-breadcrumb.mjs +14 -14
  12. package/fesm2022/ngbase-adk-breadcrumb.mjs.map +1 -1
  13. package/fesm2022/ngbase-adk-cache.mjs +3 -3
  14. package/fesm2022/ngbase-adk-cache.mjs.map +1 -1
  15. package/fesm2022/ngbase-adk-carousel.mjs +18 -18
  16. package/fesm2022/ngbase-adk-carousel.mjs.map +1 -1
  17. package/fesm2022/ngbase-adk-checkbox.mjs +15 -21
  18. package/fesm2022/ngbase-adk-checkbox.mjs.map +1 -1
  19. package/fesm2022/ngbase-adk-chip.mjs +12 -12
  20. package/fesm2022/ngbase-adk-chip.mjs.map +1 -1
  21. package/fesm2022/ngbase-adk-clipboard.mjs +7 -5
  22. package/fesm2022/ngbase-adk-clipboard.mjs.map +1 -1
  23. package/fesm2022/ngbase-adk-collections.mjs.map +1 -1
  24. package/fesm2022/ngbase-adk-color-picker.mjs +44 -53
  25. package/fesm2022/ngbase-adk-color-picker.mjs.map +1 -1
  26. package/fesm2022/ngbase-adk-cookies.mjs +3 -3
  27. package/fesm2022/ngbase-adk-cookies.mjs.map +1 -1
  28. package/fesm2022/ngbase-adk-datepicker.mjs +70 -89
  29. package/fesm2022/ngbase-adk-datepicker.mjs.map +1 -1
  30. package/fesm2022/ngbase-adk-dialog.mjs +17 -39
  31. package/fesm2022/ngbase-adk-dialog.mjs.map +1 -1
  32. package/fesm2022/ngbase-adk-drag.mjs +20 -20
  33. package/fesm2022/ngbase-adk-drag.mjs.map +1 -1
  34. package/fesm2022/ngbase-adk-form-field.mjs +65 -118
  35. package/fesm2022/ngbase-adk-form-field.mjs.map +1 -1
  36. package/fesm2022/ngbase-adk-hover-card.mjs +5 -5
  37. package/fesm2022/ngbase-adk-hover-card.mjs.map +1 -1
  38. package/fesm2022/ngbase-adk-icon.mjs +9 -11
  39. package/fesm2022/ngbase-adk-icon.mjs.map +1 -1
  40. package/fesm2022/ngbase-adk-inline-edit.mjs +27 -35
  41. package/fesm2022/ngbase-adk-inline-edit.mjs.map +1 -1
  42. package/fesm2022/ngbase-adk-jwt.mjs +6 -6
  43. package/fesm2022/ngbase-adk-jwt.mjs.map +1 -1
  44. package/fesm2022/ngbase-adk-keys.mjs +6 -6
  45. package/fesm2022/ngbase-adk-keys.mjs.map +1 -1
  46. package/fesm2022/ngbase-adk-layout.mjs.map +1 -1
  47. package/fesm2022/ngbase-adk-list.mjs +10 -10
  48. package/fesm2022/ngbase-adk-list.mjs.map +1 -1
  49. package/fesm2022/ngbase-adk-mask.mjs +8 -8
  50. package/fesm2022/ngbase-adk-mask.mjs.map +1 -1
  51. package/fesm2022/ngbase-adk-menu.mjs +69 -79
  52. package/fesm2022/ngbase-adk-menu.mjs.map +1 -1
  53. package/fesm2022/ngbase-adk-network.mjs +3 -3
  54. package/fesm2022/ngbase-adk-network.mjs.map +1 -1
  55. package/fesm2022/ngbase-adk-otp.mjs +24 -45
  56. package/fesm2022/ngbase-adk-otp.mjs.map +1 -1
  57. package/fesm2022/ngbase-adk-pagination.mjs +9 -9
  58. package/fesm2022/ngbase-adk-pagination.mjs.map +1 -1
  59. package/fesm2022/ngbase-adk-popover.mjs +120 -89
  60. package/fesm2022/ngbase-adk-popover.mjs.map +1 -1
  61. package/fesm2022/ngbase-adk-portal.mjs +139 -47
  62. package/fesm2022/ngbase-adk-portal.mjs.map +1 -1
  63. package/fesm2022/ngbase-adk-progress.mjs +7 -7
  64. package/fesm2022/ngbase-adk-progress.mjs.map +1 -1
  65. package/fesm2022/ngbase-adk-radio.mjs +20 -27
  66. package/fesm2022/ngbase-adk-radio.mjs.map +1 -1
  67. package/fesm2022/ngbase-adk-resizable.mjs +138 -48
  68. package/fesm2022/ngbase-adk-resizable.mjs.map +1 -1
  69. package/fesm2022/ngbase-adk-scroll-area.mjs +28 -20
  70. package/fesm2022/ngbase-adk-scroll-area.mjs.map +1 -1
  71. package/fesm2022/ngbase-adk-select.mjs +58 -80
  72. package/fesm2022/ngbase-adk-select.mjs.map +1 -1
  73. package/fesm2022/ngbase-adk-selectable.mjs +19 -30
  74. package/fesm2022/ngbase-adk-selectable.mjs.map +1 -1
  75. package/fesm2022/ngbase-adk-sheet.mjs +6 -20
  76. package/fesm2022/ngbase-adk-sheet.mjs.map +1 -1
  77. package/fesm2022/ngbase-adk-sidenav.mjs +65 -48
  78. package/fesm2022/ngbase-adk-sidenav.mjs.map +1 -1
  79. package/fesm2022/ngbase-adk-slider.mjs +40 -53
  80. package/fesm2022/ngbase-adk-slider.mjs.map +1 -1
  81. package/fesm2022/ngbase-adk-sonner.mjs +12 -19
  82. package/fesm2022/ngbase-adk-sonner.mjs.map +1 -1
  83. package/fesm2022/ngbase-adk-stepper.mjs +17 -25
  84. package/fesm2022/ngbase-adk-stepper.mjs.map +1 -1
  85. package/fesm2022/ngbase-adk-switch.mjs +25 -32
  86. package/fesm2022/ngbase-adk-switch.mjs.map +1 -1
  87. package/fesm2022/ngbase-adk-table.mjs +581 -83
  88. package/fesm2022/ngbase-adk-table.mjs.map +1 -1
  89. package/fesm2022/ngbase-adk-tabs.mjs +37 -35
  90. package/fesm2022/ngbase-adk-tabs.mjs.map +1 -1
  91. package/fesm2022/ngbase-adk-test.mjs.map +1 -1
  92. package/fesm2022/ngbase-adk-toggle-group.mjs +20 -34
  93. package/fesm2022/ngbase-adk-toggle-group.mjs.map +1 -1
  94. package/fesm2022/ngbase-adk-toggle.mjs +14 -19
  95. package/fesm2022/ngbase-adk-toggle.mjs.map +1 -1
  96. package/fesm2022/ngbase-adk-tooltip.mjs +12 -19
  97. package/fesm2022/ngbase-adk-tooltip.mjs.map +1 -1
  98. package/fesm2022/ngbase-adk-tour.mjs +47 -52
  99. package/fesm2022/ngbase-adk-tour.mjs.map +1 -1
  100. package/fesm2022/ngbase-adk-translate.mjs +8 -10
  101. package/fesm2022/ngbase-adk-translate.mjs.map +1 -1
  102. package/fesm2022/ngbase-adk-tree.mjs +20 -20
  103. package/fesm2022/ngbase-adk-tree.mjs.map +1 -1
  104. package/fesm2022/ngbase-adk-utils.mjs +30 -43
  105. package/fesm2022/ngbase-adk-utils.mjs.map +1 -1
  106. package/fesm2022/ngbase-adk-virtualizer.mjs +9 -9
  107. package/fesm2022/ngbase-adk-virtualizer.mjs.map +1 -1
  108. package/package.json +101 -101
  109. package/schematics/components/files/accordion/accordion.ts.template +10 -5
  110. package/schematics/components/files/audio/AudioPlayer.ts.template +245 -0
  111. package/schematics/components/files/audio/AudioRecorder.ts.template +377 -0
  112. package/schematics/components/files/audio/AudioVisualizer.ts.template +175 -0
  113. package/schematics/components/files/audio/index.ts.template +3 -0
  114. package/schematics/components/files/badge/badge-llm.md.template +2 -2
  115. package/schematics/components/files/badge/badge.ts.template +29 -9
  116. package/schematics/components/files/card/card.ts.template +1 -1
  117. package/schematics/components/files/charts/area-chart.component.ts.template +278 -0
  118. package/schematics/components/files/charts/bar-chart.component.ts.template +262 -0
  119. package/schematics/components/files/charts/chart-tooltip.component.ts.template +168 -0
  120. package/schematics/components/files/charts/index.ts.template +4 -0
  121. package/schematics/components/files/charts/line-chart.component.ts.template +238 -0
  122. package/schematics/components/files/charts/pie-chart.component.ts.template +283 -0
  123. package/schematics/components/files/checkbox/checkbox.ts.template +4 -7
  124. package/schematics/components/files/color-picker/color-picker.ts.template +2 -2
  125. package/schematics/components/files/dialog/dialog.ts.template +11 -14
  126. package/schematics/components/files/drawer/drawer.ts.template +25 -28
  127. package/schematics/components/files/form-field/form-field.ts.template +59 -23
  128. package/schematics/components/files/inline-edit/inline-edit.ts.template +3 -1
  129. package/schematics/components/files/pagination/pagination.ts.template +6 -6
  130. package/schematics/components/files/picasa/picasa-base.component.ts.template +9 -30
  131. package/schematics/components/files/popover/popover.ts.template +9 -4
  132. package/schematics/components/files/select/list-selection.ts.template +0 -2
  133. package/schematics/components/files/select/option.ts.template +1 -1
  134. package/schematics/components/files/selectable/selectable.ts.template +2 -2
  135. package/schematics/components/files/sheet/sheet.ts.template +20 -14
  136. package/schematics/components/files/sidenav/sidenav.ts.template +69 -6
  137. package/schematics/components/files/sonner/sonner.ts.template +1 -2
  138. package/schematics/components/files/stepper/stepper-llm.md.template +7 -0
  139. package/schematics/components/files/stepper/stepper.ts.template +2 -4
  140. package/schematics/components/files/switch/switch.ts.template +2 -2
  141. package/schematics/components/files/table/table-llm.md.template +14 -2
  142. package/schematics/components/files/table/table.ts.template +42 -3
  143. package/schematics/components/files/theme/theme.service.ts.template +3 -3
  144. package/schematics/components/files/toggle/toggle.ts.template +1 -1
  145. package/schematics/components/files/toggle-group/toggle-group.ts.template +1 -1
  146. package/schematics/components/files/tooltip/tooltip.ts.template +2 -3
  147. package/{accordion/index.d.ts → types/ngbase-adk-accordion.d.ts} +1 -3
  148. package/{autocomplete/index.d.ts → types/ngbase-adk-autocomplete.d.ts} +2 -7
  149. package/{checkbox/index.d.ts → types/ngbase-adk-checkbox.d.ts} +8 -14
  150. package/types/ngbase-adk-clipboard.d.ts +12 -0
  151. package/{color-picker/index.d.ts → types/ngbase-adk-color-picker.d.ts} +14 -26
  152. package/{datepicker/index.d.ts → types/ngbase-adk-datepicker.d.ts} +9 -18
  153. package/{dialog/index.d.ts → types/ngbase-adk-dialog.d.ts} +3 -8
  154. package/types/ngbase-adk-form-field.d.ts +88 -0
  155. package/{inline-edit/index.d.ts → types/ngbase-adk-inline-edit.d.ts} +8 -16
  156. package/{menu/index.d.ts → types/ngbase-adk-menu.d.ts} +6 -5
  157. package/{otp/index.d.ts → types/ngbase-adk-otp.d.ts} +8 -16
  158. package/{popover/index.d.ts → types/ngbase-adk-popover.d.ts} +14 -2
  159. package/{portal/index.d.ts → types/ngbase-adk-portal.d.ts} +30 -8
  160. package/{radio/index.d.ts → types/ngbase-adk-radio.d.ts} +9 -12
  161. package/{resizable/index.d.ts → types/ngbase-adk-resizable.d.ts} +4 -4
  162. package/{scroll-area/index.d.ts → types/ngbase-adk-scroll-area.d.ts} +2 -1
  163. package/{select/index.d.ts → types/ngbase-adk-select.d.ts} +8 -22
  164. package/{selectable/index.d.ts → types/ngbase-adk-selectable.d.ts} +6 -10
  165. package/{sheet/index.d.ts → types/ngbase-adk-sheet.d.ts} +4 -3
  166. package/{sidenav/index.d.ts → types/ngbase-adk-sidenav.d.ts} +7 -8
  167. package/{slider/index.d.ts → types/ngbase-adk-slider.d.ts} +8 -17
  168. package/{sonner/index.d.ts → types/ngbase-adk-sonner.d.ts} +1 -3
  169. package/{stepper/index.d.ts → types/ngbase-adk-stepper.d.ts} +1 -4
  170. package/{switch/index.d.ts → types/ngbase-adk-switch.d.ts} +7 -14
  171. package/{table/index.d.ts → types/ngbase-adk-table.d.ts} +126 -3
  172. package/{test/index.d.ts → types/ngbase-adk-test.d.ts} +1 -1
  173. package/{toggle-group/index.d.ts → types/ngbase-adk-toggle-group.d.ts} +5 -10
  174. package/types/ngbase-adk-toggle.d.ts +14 -0
  175. package/{tooltip/index.d.ts → types/ngbase-adk-tooltip.d.ts} +9 -11
  176. package/{tour/index.d.ts → types/ngbase-adk-tour.d.ts} +3 -6
  177. package/{utils/index.d.ts → types/ngbase-adk-utils.d.ts} +15 -11
  178. package/clipboard/index.d.ts +0 -11
  179. package/form-field/index.d.ts +0 -97
  180. package/toggle/index.d.ts +0 -16
  181. /package/{a11y/index.d.ts → types/ngbase-adk-a11y.d.ts} +0 -0
  182. /package/{avatar/index.d.ts → types/ngbase-adk-avatar.d.ts} +0 -0
  183. /package/{bidi/index.d.ts → types/ngbase-adk-bidi.d.ts} +0 -0
  184. /package/{breadcrumb/index.d.ts → types/ngbase-adk-breadcrumb.d.ts} +0 -0
  185. /package/{cache/index.d.ts → types/ngbase-adk-cache.d.ts} +0 -0
  186. /package/{carousel/index.d.ts → types/ngbase-adk-carousel.d.ts} +0 -0
  187. /package/{chip/index.d.ts → types/ngbase-adk-chip.d.ts} +0 -0
  188. /package/{collections/index.d.ts → types/ngbase-adk-collections.d.ts} +0 -0
  189. /package/{cookies/index.d.ts → types/ngbase-adk-cookies.d.ts} +0 -0
  190. /package/{drag/index.d.ts → types/ngbase-adk-drag.d.ts} +0 -0
  191. /package/{hover-card/index.d.ts → types/ngbase-adk-hover-card.d.ts} +0 -0
  192. /package/{icon/index.d.ts → types/ngbase-adk-icon.d.ts} +0 -0
  193. /package/{jwt/index.d.ts → types/ngbase-adk-jwt.d.ts} +0 -0
  194. /package/{keys/index.d.ts → types/ngbase-adk-keys.d.ts} +0 -0
  195. /package/{layout/index.d.ts → types/ngbase-adk-layout.d.ts} +0 -0
  196. /package/{list/index.d.ts → types/ngbase-adk-list.d.ts} +0 -0
  197. /package/{mask/index.d.ts → types/ngbase-adk-mask.d.ts} +0 -0
  198. /package/{network/index.d.ts → types/ngbase-adk-network.d.ts} +0 -0
  199. /package/{pagination/index.d.ts → types/ngbase-adk-pagination.d.ts} +0 -0
  200. /package/{progress/index.d.ts → types/ngbase-adk-progress.d.ts} +0 -0
  201. /package/{tabs/index.d.ts → types/ngbase-adk-tabs.d.ts} +0 -0
  202. /package/{translate/index.d.ts → types/ngbase-adk-translate.d.ts} +0 -0
  203. /package/{tree/index.d.ts → types/ngbase-adk-tree.d.ts} +0 -0
  204. /package/{virtualizer/index.d.ts → types/ngbase-adk-virtualizer.d.ts} +0 -0
  205. /package/{index.d.ts → types/ngbase-adk.d.ts} +0 -0
@@ -0,0 +1,238 @@
1
+ import {
2
+ ChangeDetectionStrategy,
3
+ Component,
4
+ ElementRef,
5
+ afterNextRender,
6
+ input,
7
+ viewChild,
8
+ effect,
9
+ signal,
10
+ } from '@angular/core';
11
+ import * as d3 from 'd3';
12
+ import { ChartTooltipComponent, TooltipContent } from './chart-tooltip.component';
13
+
14
+ interface LineData {
15
+ label: string;
16
+ value: number;
17
+ }
18
+
19
+ @Component({
20
+ selector: '<%= name %>-line-chart',
21
+ changeDetection: ChangeDetectionStrategy.OnPush,
22
+ imports: [ChartTooltipComponent],
23
+ template: `
24
+ <svg #chart class="w-full"></svg>
25
+ <<%= name %>-chart-tooltip
26
+ [visible]="tooltipVisible()"
27
+ [x]="tooltipX()"
28
+ [y]="tooltipY()"
29
+ [content]="tooltipContent()"
30
+ />
31
+ `,
32
+ host: {
33
+ class: 'block relative',
34
+ },
35
+ })
36
+ export class LineChartComponent {
37
+ readonly chartRef = viewChild.required<ElementRef<SVGElement>>('chart');
38
+
39
+ data = input.required<LineData[]>();
40
+
41
+ height = input(250);
42
+ showYAxis = input(false);
43
+
44
+ private svg!: d3.Selection<SVGElement, unknown, null, undefined>;
45
+ private margin = { top: 20, right: 20, bottom: 50, left: 50 };
46
+
47
+ // Tooltip state
48
+ tooltipVisible = signal(false);
49
+ tooltipX = signal(0);
50
+ tooltipY = signal(0);
51
+ tooltipContent = signal<TooltipContent>({ label: '', value: 0 });
52
+
53
+ private resizeObserver: ResizeObserver | undefined;
54
+
55
+ constructor() {
56
+ afterNextRender(() => {
57
+ this.svg = d3.select(this.chartRef().nativeElement);
58
+ this.updateChart();
59
+
60
+ this.resizeObserver = new ResizeObserver(() => {
61
+ this.updateChart();
62
+ });
63
+ this.resizeObserver.observe(this.chartRef().nativeElement.parentElement!);
64
+ });
65
+
66
+ // Watch for input changes and update chart
67
+ effect(() => {
68
+ const data = this.data();
69
+ const _height = this.height();
70
+ const _showYAxis = this.showYAxis();
71
+
72
+ // Update chart if svg is initialized
73
+ if (this.svg && data) {
74
+ this.updateChart();
75
+ }
76
+ });
77
+ }
78
+
79
+ ngOnDestroy() {
80
+ if (this.resizeObserver) {
81
+ this.resizeObserver.disconnect();
82
+ }
83
+ }
84
+
85
+ private updateChart(): void {
86
+ if (!this.svg) return;
87
+
88
+ const data = this.data();
89
+ // Get actual width from parent container
90
+ const containerWidth = this.chartRef().nativeElement.parentElement?.clientWidth || 0;
91
+
92
+ if (containerWidth === 0) return;
93
+
94
+ // Adjust left margin based on showYAxis
95
+ const leftMargin = this.showYAxis() ? this.margin.left : 20;
96
+ const width = containerWidth - leftMargin - this.margin.right;
97
+ const height = this.height() - this.margin.top - this.margin.bottom;
98
+
99
+ // Clear previous content
100
+ this.svg.selectAll('*').remove();
101
+
102
+ // Set SVG dimensions - width/height/viewBox must match
103
+ this.svg
104
+ .attr('width', containerWidth)
105
+ .attr('height', this.height())
106
+ .attr('viewBox', `0 0 ${containerWidth} ${this.height()}`);
107
+
108
+ // Create chart group
109
+ const g = this.svg.append('g').attr('transform', `translate(${leftMargin},${this.margin.top})`);
110
+
111
+ // Get CSS variables for theming
112
+ const textColor = getComputedStyle(document.documentElement)
113
+ .getPropertyValue('--color-text')
114
+ .trim();
115
+ const borderColor = getComputedStyle(document.documentElement)
116
+ .getPropertyValue('--color-border')
117
+ .trim();
118
+
119
+ // Get chart color (using chart-1 for line)
120
+ const lineColor = getComputedStyle(document.documentElement)
121
+ .getPropertyValue('--chart-1')
122
+ .trim();
123
+
124
+ // Create scales
125
+ const x = d3
126
+ .scalePoint()
127
+ .domain(data.map(d => d.label))
128
+ .range([0, width])
129
+ .padding(0.5);
130
+
131
+ const y = d3
132
+ .scaleLinear()
133
+ .domain([0, d3.max(data, d => d.value) || 100])
134
+ .nice()
135
+ .range([height, 0]);
136
+
137
+ // Add X axis
138
+ g.append('g')
139
+ .attr('transform', `translate(0,${height})`)
140
+ .call(d3.axisBottom(x))
141
+ .style('color', textColor)
142
+ .selectAll('text')
143
+ .style('font-size', '12px');
144
+
145
+ // Add Y axis (conditionally)
146
+ if (this.showYAxis()) {
147
+ g.append('g')
148
+ .call(d3.axisLeft(y))
149
+ .style('color', textColor)
150
+ .selectAll('text')
151
+ .style('font-size', '12px');
152
+ }
153
+
154
+ // Style axis lines
155
+ g.selectAll('.domain, .tick line').style('stroke', borderColor);
156
+
157
+ // Add grid lines
158
+ g.append('g')
159
+ .attr('class', 'grid')
160
+ .call(
161
+ d3
162
+ .axisLeft(y)
163
+ .tickSize(-width)
164
+ .tickFormat(() => ''),
165
+ )
166
+ .select('.domain')
167
+ .remove();
168
+
169
+ // Style grid lines
170
+ g.selectAll('.grid .tick line').style('stroke', 'rgb(229 229 229 / 50%)');
171
+
172
+ // Create line generator
173
+ const line = d3
174
+ .line<LineData>()
175
+ .x(d => x(d.label) || 0)
176
+ .y(d => y(d.value))
177
+ .curve(d3.curveMonotoneX);
178
+
179
+ // Add the line path
180
+ const path = g
181
+ .append('path')
182
+ .datum(data)
183
+ .attr('fill', 'none')
184
+ .attr('stroke', lineColor)
185
+ .attr('stroke-width', 2)
186
+ .attr('d', line);
187
+
188
+ // Animate line drawing
189
+ const totalLength = path.node()?.getTotalLength() || 0;
190
+ path
191
+ .attr('stroke-dasharray', `${totalLength} ${totalLength}`)
192
+ .attr('stroke-dashoffset', totalLength)
193
+ .transition()
194
+ .duration(1200)
195
+ .ease(d3.easeLinear)
196
+ .attr('stroke-dashoffset', 0);
197
+
198
+ // Add circles for data points
199
+ const circles = g
200
+ .selectAll('.dot')
201
+ .data(data)
202
+ .enter()
203
+ .append('circle')
204
+ .attr('class', 'dot')
205
+ .attr('cx', d => x(d.label) || 0)
206
+ .attr('cy', d => y(d.value))
207
+ .attr('r', 0)
208
+ .attr('fill', lineColor)
209
+ .attr('stroke', 'transparent')
210
+ .attr('stroke-width', 2)
211
+ .style('cursor', 'pointer');
212
+
213
+ // Add hover effects for tooltip
214
+ circles
215
+ .on('mouseenter', (event, d) => {
216
+ const circleX = x(d.label) || 0;
217
+ const circleY = y(d.value);
218
+ const svgRect = this.chartRef().nativeElement.getBoundingClientRect();
219
+
220
+ this.tooltipContent.set({ label: d.label, value: d.value });
221
+ this.tooltipX.set(svgRect.left + leftMargin + circleX);
222
+ this.tooltipY.set(svgRect.top + this.margin.top + circleY - 10);
223
+ this.tooltipVisible.set(true);
224
+
225
+ // Enlarge circle on hover
226
+ d3.select(event.currentTarget).transition().duration(200).attr('r', 7);
227
+ })
228
+ .on('mouseleave', event => {
229
+ this.tooltipVisible.set(false);
230
+
231
+ // Restore circle size
232
+ d3.select(event.currentTarget).transition().duration(200).attr('r', 4);
233
+ });
234
+
235
+ // Animate circles
236
+ circles.transition().delay(1200).duration(400).attr('r', 4);
237
+ }
238
+ }
@@ -0,0 +1,283 @@
1
+ import {
2
+ ChangeDetectionStrategy,
3
+ Component,
4
+ ElementRef,
5
+ afterNextRender,
6
+ input,
7
+ viewChild,
8
+ effect,
9
+ signal,
10
+ } from '@angular/core';
11
+ import * as d3 from 'd3';
12
+ import { ChartTooltipComponent, TooltipContent } from './chart-tooltip.component';
13
+
14
+ interface PieData {
15
+ label: string;
16
+ value: number;
17
+ }
18
+
19
+ @Component({
20
+ selector: '<%= name %>-pie-chart',
21
+ changeDetection: ChangeDetectionStrategy.OnPush,
22
+ imports: [ChartTooltipComponent],
23
+ template: `
24
+ <svg #chart class="w-full"></svg>
25
+ <<%= name %>-chart-tooltip
26
+ [visible]="tooltipVisible()"
27
+ [x]="tooltipX()"
28
+ [y]="tooltipY()"
29
+ [content]="tooltipContent()"
30
+ />
31
+ `,
32
+ host: {
33
+ class: 'flex justify-center block relative',
34
+ },
35
+ })
36
+ export class PieChartComponent {
37
+ readonly chartRef = viewChild.required<ElementRef<SVGElement>>('chart');
38
+
39
+ data = input.required<PieData[]>();
40
+
41
+ height = input(300);
42
+ innerRadius = input(0); // Set to 0 for pie, >0 for donut
43
+
44
+ private svg!: d3.Selection<SVGElement, unknown, null, undefined>;
45
+
46
+ // Tooltip state
47
+ tooltipVisible = signal(false);
48
+ tooltipX = signal(0);
49
+ tooltipY = signal(0);
50
+ tooltipContent = signal<TooltipContent>({ label: '', value: 0 });
51
+
52
+ private resizeObserver: ResizeObserver | undefined;
53
+
54
+ constructor() {
55
+ afterNextRender(() => {
56
+ this.svg = d3.select(this.chartRef().nativeElement);
57
+ this.updateChart();
58
+
59
+ this.resizeObserver = new ResizeObserver(() => {
60
+ this.updateChart();
61
+ });
62
+ this.resizeObserver.observe(this.chartRef().nativeElement.parentElement!);
63
+ });
64
+
65
+ // Watch for input changes and update chart
66
+ effect(() => {
67
+ const data = this.data();
68
+ const _height = this.height();
69
+ const _innerRadius = this.innerRadius();
70
+
71
+ // Update chart if svg is initialized
72
+ if (this.svg && data) {
73
+ this.updateChart();
74
+ }
75
+ });
76
+ }
77
+
78
+ ngOnDestroy() {
79
+ if (this.resizeObserver) {
80
+ this.resizeObserver.disconnect();
81
+ }
82
+ }
83
+
84
+ private updateChart(): void {
85
+ if (!this.svg) return;
86
+
87
+ const data = this.data();
88
+ // Get actual width from parent container
89
+ const containerWidth = this.chartRef().nativeElement.parentElement?.clientWidth || 0;
90
+
91
+ if (containerWidth === 0) return;
92
+
93
+ const width = containerWidth;
94
+ const height = this.height();
95
+
96
+ // Legend configuration
97
+ const itemWidth = 120; // Width for each legend item
98
+ const itemsPerRow = Math.max(1, Math.floor(width / itemWidth));
99
+ const legendPadding = 25; // Vertical spacing between rows
100
+ const numRows = Math.ceil(data.length / itemsPerRow);
101
+ const legendHeight = numRows * legendPadding; // Total calculated legend height
102
+
103
+ // Calculate available space for pie chart
104
+ // Reserve space for margins and legend
105
+ const chartMargin = 20;
106
+ const availableHeight = height - legendHeight - chartMargin;
107
+ const availableWidth = width;
108
+
109
+ // Calculate radius to fit in available space
110
+ const radius = Math.min(availableWidth, availableHeight) / 2 - 10;
111
+
112
+ // Calculate center efficiency
113
+ const centerY = availableHeight / 2 + chartMargin / 2;
114
+ const centerX = width / 2;
115
+
116
+ // Clear previous content
117
+ this.svg.selectAll('*').remove();
118
+
119
+ // Set SVG dimensions - width/height/viewBox must match
120
+ this.svg
121
+ .attr('width', containerWidth)
122
+ .attr('height', this.height())
123
+ .attr('viewBox', `0 0 ${containerWidth} ${this.height()}`);
124
+
125
+ // Get CSS variables for theming
126
+ const textColor = getComputedStyle(document.documentElement)
127
+ .getPropertyValue('--color-text')
128
+ .trim();
129
+
130
+ // Get chart colors
131
+ const chartColors = Array.from({ length: 5 }, (_, i) =>
132
+ getComputedStyle(document.documentElement)
133
+ .getPropertyValue(`--chart-${i + 1}`)
134
+ .trim(),
135
+ );
136
+
137
+ // Create color scale using chart colors
138
+ const colorScale = d3
139
+ .scaleOrdinal<string>()
140
+ .domain(data.map(d => d.label))
141
+ .range(chartColors);
142
+
143
+ // Create chart group
144
+ const g = this.svg.append('g').attr('transform', `translate(${centerX},${centerY})`);
145
+
146
+ // Create pie layout
147
+ const pie = d3
148
+ .pie<PieData>()
149
+ .value(d => d.value)
150
+ .sort(null);
151
+
152
+ // Create arc generator
153
+ const arc = d3
154
+ .arc<d3.PieArcDatum<PieData>>()
155
+ .innerRadius(this.innerRadius())
156
+ .outerRadius(radius);
157
+
158
+ // Create arc for hover effect
159
+ const arcHover = d3
160
+ .arc<d3.PieArcDatum<PieData>>()
161
+ .innerRadius(this.innerRadius())
162
+ .outerRadius(radius + 10);
163
+
164
+ // Create arcs
165
+ const arcs = g.selectAll('.arc').data(pie(data)).enter().append('g').attr('class', 'arc');
166
+
167
+ // Add paths with animation
168
+ const paths = arcs
169
+ .append('path')
170
+ .attr('fill', d => colorScale(d.data.label))
171
+ .style('cursor', 'pointer');
172
+
173
+ // Add hover effects for tooltip
174
+ paths
175
+ .on('mouseenter', (event, d) => {
176
+ const total = d3.sum(data, item => item.value);
177
+ const percentage = ((d.data.value / total) * 100).toFixed(1);
178
+
179
+ this.tooltipContent.set({
180
+ label: d.data.label,
181
+ value: d.data.value,
182
+ percentage: parseFloat(percentage),
183
+ });
184
+ this.tooltipX.set(event.clientX);
185
+ this.tooltipY.set(event.clientY);
186
+ this.tooltipVisible.set(true);
187
+
188
+ // Expand arc on hover
189
+ d3.select(event.currentTarget)
190
+ .transition()
191
+ .duration(200)
192
+ .attr('d', arcHover as any);
193
+ })
194
+ .on('mousemove', event => {
195
+ this.tooltipX.set(event.clientX);
196
+ this.tooltipY.set(event.clientY);
197
+ })
198
+ .on('mouseleave', event => {
199
+ this.tooltipVisible.set(false);
200
+
201
+ // Restore arc size
202
+ d3.select(event.currentTarget)
203
+ .transition()
204
+ .duration(200)
205
+ .attr('d', arc as any);
206
+ });
207
+
208
+ // Animate paths
209
+ paths
210
+ .transition()
211
+ .duration(800)
212
+ .attrTween('d', function (d) {
213
+ const interpolate = d3.interpolate({ startAngle: 0, endAngle: 0 }, d);
214
+ return function (t) {
215
+ return arc(interpolate(t) as any) || '';
216
+ };
217
+ });
218
+
219
+ // Add labels (only if slice is big enough)
220
+ arcs
221
+ .filter(d => d.endAngle - d.startAngle > 0.25)
222
+ .append('text')
223
+ .attr('transform', d => {
224
+ const [x, y] = arc.centroid(d);
225
+ return `translate(${x},${y})`;
226
+ })
227
+ .attr('text-anchor', 'middle')
228
+ .style('font-size', '12px')
229
+ .style('font-weight', '600')
230
+ .style('fill', 'white')
231
+ .style('opacity', 0)
232
+ .text(d => `${d.data.value}`)
233
+ .transition()
234
+ .delay(800)
235
+ .duration(400)
236
+ .style('opacity', 1);
237
+
238
+ // Add legend at the bottom with wrapping
239
+ const legendStartY = availableHeight + chartMargin; // Start logic below the chart area
240
+ const legend = this.svg.append('g').attr('transform', `translate(0, ${legendStartY})`);
241
+
242
+ const legendItems = legend
243
+ .selectAll('.legend-item')
244
+ .data(data)
245
+ .enter()
246
+ .append('g')
247
+ .attr('class', 'legend-item')
248
+ .attr('transform', (_d, i) => {
249
+ const row = Math.floor(i / itemsPerRow);
250
+ const col = i % itemsPerRow;
251
+ const itemsInCurrentRow = Math.min(itemsPerRow, data.length - row * itemsPerRow);
252
+ const rowWidth = itemsInCurrentRow * itemWidth;
253
+ const rowStartX = (width - rowWidth) / 2;
254
+ return `translate(${rowStartX + col * itemWidth}, ${row * legendPadding})`;
255
+ });
256
+
257
+ legendItems
258
+ .append('rect')
259
+ .attr('width', 8)
260
+ .attr('height', 8)
261
+ .attr('rx', 2)
262
+ .attr('fill', d => colorScale(d.label))
263
+ .style('opacity', 0)
264
+ .transition()
265
+ .delay((d, i) => 800 + i * 100)
266
+ .duration(400)
267
+ .style('opacity', 1);
268
+
269
+ legendItems
270
+ .append('text')
271
+ .attr('x', 14)
272
+ .attr('y', 4)
273
+ .attr('dy', '0.35em')
274
+ .style('font-size', '12px')
275
+ .style('fill', textColor)
276
+ .text(d => d.label)
277
+ .style('opacity', 0)
278
+ .transition()
279
+ .delay((d, i) => 800 + i * 100)
280
+ .duration(400)
281
+ .style('opacity', 1);
282
+ }
283
+ }
@@ -1,5 +1,4 @@
1
1
  import { ChangeDetectionStrategy, Component, computed } from '@angular/core';
2
- import { FormsModule } from '@angular/forms';
3
2
  import { FocusStyle } from './focus-style.directive';
4
3
  import { CheckboxButton, NgbCheckbox, aliasCheckbox } from '@ngbase/adk/checkbox';
5
4
 
@@ -7,18 +6,16 @@ import { CheckboxButton, NgbCheckbox, aliasCheckbox } from '@ngbase/adk/checkbox
7
6
  selector: '<%= name %>-checkbox',
8
7
  changeDetection: ChangeDetectionStrategy.OnPush,
9
8
  providers: [aliasCheckbox(Checkbox)],
10
- imports: [FormsModule, FocusStyle, CheckboxButton],
9
+ imports: [FocusStyle, CheckboxButton],
11
10
  template: `
12
11
  <button
13
12
  <%= name %>FocusStyle
14
13
  ngbCheckboxButton
15
- class="custom-checkbox relative flex h-4 w-4 flex-none items-center justify-center rounded border border-primary transition-colors"
16
- [class]="
17
- disabled() ? '!border-muted-foreground bg-muted-foreground' : path() ? 'bg-primary' : ''
18
- "
14
+ class="custom-checkbox border-primary relative flex h-4 w-4 flex-none items-center justify-center rounded border transition-colors"
15
+ [class]="disabled() ? 'border-muted-foreground!' : path() ? 'bg-primary' : ''"
19
16
  >
20
17
  @if (path(); as d) {
21
- <svg class="h-full w-full text-background" viewBox="0 0 24 24" aria-hidden="true">
18
+ <svg class="text-background h-full w-full" viewBox="0 0 24 24" aria-hidden="true">
22
19
  <path [attr.d]="d" stroke="currentColor" stroke-width="2" fill="none" />
23
20
  </svg>
24
21
  }
@@ -31,7 +31,7 @@ import { InputBase } from '@ngbase/adk/form-field';
31
31
  <div ngbColorSpectrum class="relative h-[160px] w-full overflow-hidden rounded-md border-b">
32
32
  <button
33
33
  ngbColorSpectrumSelector
34
- class="pointer-events-none absolute -left-2 -top-2 h-4 w-4 cursor-pointer rounded-full border"
34
+ class="pointer-events-none absolute -top-2 -left-2 h-4 w-4 cursor-pointer rounded-full border"
35
35
  ></button>
36
36
  </div>
37
37
  <div class="flex gap-4 p-3">
@@ -75,7 +75,7 @@ export class ColorPicker extends NgbColorPicker {}
75
75
  @Component({
76
76
  selector: '<%= name %>-color-input',
77
77
  changeDetection: ChangeDetectionStrategy.OnPush,
78
- providers: [registerColorPicker({ picker: ColorPicker, accessor: ColorInput })],
78
+ providers: [registerColorPicker(ColorPicker)],
79
79
  imports: [ColorPickerTrigger, InputBase],
80
80
  template: `
81
81
  <input
@@ -11,10 +11,8 @@ import {
11
11
  NgbDialogContainer,
12
12
  NgbDialogMain,
13
13
  ngbDialogPortal,
14
- viewAnimation,
15
14
  } from '@ngbase/adk/dialog';
16
15
  import { DragMove } from '@ngbase/adk/drag';
17
- import { createHostAnimation, fadeAnimation } from '@ngbase/adk/utils';
18
16
 
19
17
  @Component({
20
18
  selector: '<%= name %>-dialog',
@@ -27,13 +25,14 @@ import { createHostAnimation, fadeAnimation } from '@ngbase/adk/utils';
27
25
  <div
28
26
  #myDialog
29
27
  ngbDialogMain
30
- [@viewAnimation]
31
28
  class="{{
32
29
  'pointer-events-auto relative flex max-w-[100vw] flex-col overflow-hidden border bg-background shadow-lg' +
33
30
  (options().fullWindow
34
31
  ? ' h-screen w-screen border-none'
35
- : ' max-w-[calc(100vw-30px)] rounded-lg')
32
+ : ' max-w-[calc(100vw-30px)] rounded-lg') +
33
+ (closing() ? ' dialog-content-leave' : ' dialog-content')
36
34
  }}"
35
+ (animationend)="onAnimationEnd($event)"
37
36
  >
38
37
  @if (!isHideHeader) {
39
38
  <div
@@ -55,25 +54,23 @@ import { createHostAnimation, fadeAnimation } from '@ngbase/adk/utils';
55
54
  </div>
56
55
  @if (showBackdrop()) {
57
56
  <div
58
- class="pointer-events-auto absolute top-0 -z-10 h-full w-full bg-black/30"
59
- [@fadeAnimation]
60
57
  ngbDialogBackdrop
58
+ (animationend)="onAnimationEnd($event)"
59
+ class="{{
60
+ 'pointer-events-auto absolute top-0 -z-10 h-full w-full bg-black/30' +
61
+ (closing() ? ' dialog-backdrop-leave' : ' dialog-backdrop')
62
+ }}"
61
63
  ></div>
62
64
  }
63
65
  </div>
64
66
  `,
65
67
  host: {
66
68
  class: 'fixed block top-0 bottom-0 left-0 right-0 overflow-auto pointer-events-none z-p',
67
- '[@parentAnimation]': '',
68
- '(@parentAnimation.done)': 'animationDone()',
69
69
  },
70
- animations: [
71
- createHostAnimation(['@viewAnimation', '@fadeAnimation']),
72
- fadeAnimation('200ms'),
73
- viewAnimation,
74
- ],
75
70
  })
76
- export class DialogContainer extends NgbDialogContainer {}
71
+ export class DialogContainer extends NgbDialogContainer {
72
+ protected override readonly hasAnimations = true;
73
+ }
77
74
 
78
75
  @Directive({
79
76
  selector: '[<%= name %>DialogClose]',