ngx-kit 7.2.0 → 7.3.1

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 (72) hide show
  1. package/angle-selector/README.md +34 -34
  2. package/box-shadow/README.md +33 -33
  3. package/color-picker/README.md +52 -52
  4. package/{shared → core}/README.md +117 -117
  5. package/data-table/README.md +120 -120
  6. package/date-picker/README.md +74 -74
  7. package/dialog/README.md +122 -92
  8. package/drag-resize/README.md +53 -55
  9. package/fesm2022/ngx-kit-angle-selector.mjs +9 -26
  10. package/fesm2022/ngx-kit-angle-selector.mjs.map +1 -1
  11. package/fesm2022/ngx-kit-box-shadow.mjs +330 -356
  12. package/fesm2022/ngx-kit-box-shadow.mjs.map +1 -1
  13. package/fesm2022/ngx-kit-color-picker.mjs +132 -272
  14. package/fesm2022/ngx-kit-color-picker.mjs.map +1 -1
  15. package/fesm2022/{ngx-kit-shared.mjs → ngx-kit-core.mjs} +845 -277
  16. package/fesm2022/ngx-kit-core.mjs.map +1 -0
  17. package/fesm2022/ngx-kit-data-table.mjs +3 -3
  18. package/fesm2022/ngx-kit-data-table.mjs.map +1 -1
  19. package/fesm2022/ngx-kit-date-picker.mjs +153 -147
  20. package/fesm2022/ngx-kit-date-picker.mjs.map +1 -1
  21. package/fesm2022/ngx-kit-dialog.mjs +430 -331
  22. package/fesm2022/ngx-kit-dialog.mjs.map +1 -1
  23. package/fesm2022/ngx-kit-drag-resize.mjs +126 -45
  24. package/fesm2022/ngx-kit-drag-resize.mjs.map +1 -1
  25. package/fesm2022/ngx-kit-drawer-menu.mjs +2 -2
  26. package/fesm2022/ngx-kit-drawer-menu.mjs.map +1 -1
  27. package/fesm2022/ngx-kit-dropzone.mjs.map +1 -1
  28. package/fesm2022/ngx-kit-form-field.mjs.map +1 -1
  29. package/fesm2022/ngx-kit-gallery.mjs +3 -3
  30. package/fesm2022/ngx-kit-gallery.mjs.map +1 -1
  31. package/fesm2022/ngx-kit-gradient-picker.mjs +20 -38
  32. package/fesm2022/ngx-kit-gradient-picker.mjs.map +1 -1
  33. package/fesm2022/ngx-kit-grid-layout.mjs +19 -18
  34. package/fesm2022/ngx-kit-grid-layout.mjs.map +1 -1
  35. package/fesm2022/ngx-kit-image-editor.mjs +3 -3
  36. package/fesm2022/ngx-kit-image-editor.mjs.map +1 -1
  37. package/fesm2022/ngx-kit-menu.mjs +1 -1
  38. package/fesm2022/ngx-kit-menu.mjs.map +1 -1
  39. package/fesm2022/ngx-kit-message.mjs +1 -1
  40. package/fesm2022/ngx-kit-message.mjs.map +1 -1
  41. package/fesm2022/ngx-kit-notify.mjs +1 -1
  42. package/fesm2022/ngx-kit-notify.mjs.map +1 -1
  43. package/fesm2022/ngx-kit-time-picker.mjs +1 -1
  44. package/fesm2022/ngx-kit-time-picker.mjs.map +1 -1
  45. package/fesm2022/ngx-kit-virtual-scroll.mjs +2 -2
  46. package/fesm2022/ngx-kit-virtual-scroll.mjs.map +1 -1
  47. package/gallery/README.md +71 -71
  48. package/gradient-picker/README.md +41 -41
  49. package/grid-layout/README.md +64 -64
  50. package/image-editor/README.md +44 -44
  51. package/menu/README.md +85 -85
  52. package/message/README.md +70 -70
  53. package/notify/README.md +56 -56
  54. package/package.json +5 -9
  55. package/time-picker/README.md +89 -89
  56. package/types/ngx-kit-angle-selector.d.ts +13 -16
  57. package/types/ngx-kit-box-shadow.d.ts +37 -95
  58. package/types/ngx-kit-color-picker.d.ts +61 -58
  59. package/types/{ngx-kit-shared.d.ts → ngx-kit-core.d.ts} +156 -34
  60. package/types/ngx-kit-data-table.d.ts +2 -2
  61. package/types/ngx-kit-date-picker.d.ts +30 -29
  62. package/types/ngx-kit-dialog.d.ts +208 -107
  63. package/types/ngx-kit-drag-resize.d.ts +33 -6
  64. package/types/ngx-kit-gradient-picker.d.ts +4 -7
  65. package/types/ngx-kit-grid-layout.d.ts +0 -1
  66. package/types/ngx-kit-menu.d.ts +1 -1
  67. package/types/ngx-kit-time-picker.d.ts +1 -1
  68. package/virtual-scroll/README.md +199 -199
  69. package/fesm2022/ngx-kit-shared.mjs.map +0 -1
  70. package/fesm2022/ngx-kit-webflow.mjs +0 -709
  71. package/fesm2022/ngx-kit-webflow.mjs.map +0 -1
  72. package/types/ngx-kit-webflow.d.ts +0 -286
@@ -1,423 +1,397 @@
1
+ import { CommonModule } from '@angular/common';
1
2
  import * as i0 from '@angular/core';
2
- import { EventEmitter, inject, forwardRef, HostListener, ViewChild, Output, Input, ChangeDetectionStrategy, Component, Directive } from '@angular/core';
3
+ import { input, model, output, signal, HostListener, ViewChild, Component, inject, DOCUMENT, ChangeDetectorRef, forwardRef, ChangeDetectionStrategy } from '@angular/core';
3
4
  import * as i1 from '@angular/forms';
4
- import { FormsModule, NG_VALUE_ACCESSOR, NG_VALIDATORS } from '@angular/forms';
5
- import * as i1$1 from 'ngx-kit/shared';
6
- import { BrowserService, startDragSession, getOffsetPosition } from 'ngx-kit/shared';
5
+ import { FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
6
+ import { extractCssColors, getOffsetPosition, WINDOW, OverlayService } from 'ngx-kit/core';
7
7
  import { NgxInputColor } from 'ngx-kit/color-picker';
8
8
 
9
- function parseBoxShadowToPx(shadow, contextPx = 16) {
10
- if (!shadow || !shadow?.trim())
11
- return null;
12
- let inset = false;
13
- shadow = shadow.trim();
14
- if (shadow.startsWith('inset')) {
15
- inset = true;
16
- shadow = shadow.slice(5).trim();
17
- }
18
- const colorRegex = /(#(?:[a-f0-9]{3}|[a-f0-9]{6}|[a-f0-9]{4}|[a-f0-9]{8})\b|rgb\(\d{1,3},\s*\d{1,3},\s*\d{1,3}\)|rgba\(\d{1,3},\s*\d{1,3},\s*\d{1,3},\s*\d*(?:\.\d+)?\)|hsl\(\s*\d+,\s*\d*(?:\.\d+)?%,\s*\d*(?:\.\d+)?%\)|hsla\(\d+,\s*[\d.]+%,\s*[\d.]+%,\s*\d*(?:\.\d+)?\))/gi;
19
- const colorMatch = shadow.match(colorRegex);
20
- let color = 'black';
21
- if (colorMatch) {
22
- color = colorMatch[0];
23
- shadow = shadow.replace(color, '').trim();
24
- }
25
- const toPx = (value, unit) => {
26
- switch (unit.toLowerCase()) {
27
- case 'px':
28
- case '':
29
- return value;
30
- case 'em':
31
- case 'rem':
32
- return value * contextPx;
33
- case '%':
34
- return (value / 100) * contextPx;
35
- case 'pt':
36
- return value * 1.333;
37
- default:
38
- return value; // fallback
9
+ function parseBoxShadow(cssValue) {
10
+ if (!cssValue || typeof cssValue !== 'string') {
11
+ return [];
12
+ }
13
+ // Split multiple shadows by comma
14
+ const shadows = cssValue
15
+ .split(/,(?![^\(]*\))/)
16
+ .map((shadow) => shadow.trim())
17
+ .filter((shadow) => shadow);
18
+ const boxShadows = [];
19
+ const unitRegex = /(px|rem|em)/;
20
+ const numberRegex = /-?\d*\.?\d*(?:px|rem|em)?/g;
21
+ for (const shadow of shadows) {
22
+ const boxShadow = {
23
+ xOffset: 0,
24
+ yOffset: 0,
25
+ color: 'rgba(0, 0, 0, 0)', // Default color
26
+ unit: 'px', // Default unit
27
+ cssValue: '',
28
+ };
29
+ // Check for inset
30
+ boxShadow.inset = shadow.includes('inset');
31
+ // Extract color
32
+ const colorMatch = extractCssColors(shadow);
33
+ if (colorMatch) {
34
+ boxShadow.color = colorMatch[0];
35
+ }
36
+ // Remove inset and color to parse numbers
37
+ let numberString = shadow.replace('inset', '').replace(boxShadow.color, '').trim();
38
+ // Extract numbers
39
+ const numbers = (numberString.match(numberRegex) ?? [])
40
+ .map((shadow) => shadow.trim())
41
+ .filter((shadow) => shadow);
42
+ if (!numbers)
43
+ continue;
44
+ // Parse numbers
45
+ for (let i = 0; i < numbers.length; i++) {
46
+ const num = parseFloat(numbers[i]);
47
+ const unit = numbers[i].match(unitRegex)?.[0] || 'px';
48
+ boxShadow.unit = unit; // Update unit based on first detected unit
49
+ if (i === 0) {
50
+ boxShadow.xOffset = isNaN(num) ? 0 : num;
51
+ }
52
+ else if (i === 1) {
53
+ boxShadow.yOffset = isNaN(num) ? 0 : num;
54
+ }
55
+ else if (i === 2) {
56
+ boxShadow.blurRadius = isNaN(num) ? 0 : Math.max(0, num); // Blur can't be negative
57
+ }
58
+ else if (i === 3) {
59
+ boxShadow.spreadRadius = isNaN(num) ? 0 : num;
60
+ }
39
61
  }
40
- };
41
- const matches = [...shadow.matchAll(/(-?\d*\.?\d+)([a-zA-Z%]*)/g)];
42
- const values = matches.map(([_, num, unit]) => toPx(parseFloat(num), unit));
43
- const [offsetX, offsetY, blur, spread] = values;
44
- return {
45
- inset,
46
- offsetX: offsetX ?? 0,
47
- offsetY: offsetY ?? 0,
48
- blurRadius: blur ?? 0,
49
- spreadRadius: spread ?? 0,
50
- color,
51
- };
62
+ boxShadow.cssValue = shadow;
63
+ boxShadows.push(boxShadow);
64
+ }
65
+ return boxShadows;
52
66
  }
53
- function stringifyBoxShadow(obj) {
54
- const { inset, offsetX, offsetY, blurRadius, spreadRadius, color } = obj;
55
- const parts = [
56
- inset ? 'inset' : '',
57
- `${offsetX}px`,
58
- `${offsetY}px`,
59
- `${blurRadius}px`,
60
- `${spreadRadius}px`,
61
- color,
67
+ // Utility to validate and format color
68
+ function validateColor(color) {
69
+ const hexRegex = /^#[0-9a-fA-F]{3,8}$/;
70
+ const rgbRegex = /^rgba?\(\s*\d+\s*,\s*\d+\s*,\s*\d+\s*(,\s*[\d.]+)?\)$/;
71
+ const hslRegex = /^hsl\(\s*\d+\s*,\s*\d+%\s*,\s*\d+%\s*\)$/;
72
+ const namedColors = [
73
+ 'black',
74
+ 'white',
75
+ 'red',
76
+ 'blue',
77
+ 'green',
78
+ 'yellow',
79
+ 'purple',
80
+ 'orange',
81
+ // Add more named colors as needed
62
82
  ];
63
- return parts.filter(Boolean).join(' ').trim();
83
+ color = color.trim();
84
+ if (hexRegex.test(color) || rgbRegex.test(color) || hslRegex.test(color)) {
85
+ return color;
86
+ }
87
+ if (namedColors.includes(color.toLowerCase())) {
88
+ return color.toLowerCase();
89
+ }
90
+ return 'rgba(0, 0, 0, 0)'; // Fallback to transparent
64
91
  }
65
-
66
- class NgxBoxShadowComponent {
67
- cd;
68
- theme = 'light';
69
- set setTheme(val) {
70
- if (!val || val == 'auto') {
71
- this.theme = this.browserService.prefersDarkMode ? 'dark' : 'light';
92
+ // Utility to format BoxShadow back to CSS string
93
+ function formatBoxShadowToCSS(shadows) {
94
+ return shadows
95
+ .map((shadow) => {
96
+ const parts = [];
97
+ if (shadow.inset) {
98
+ parts.push('inset');
72
99
  }
73
- else {
74
- this.theme = val;
100
+ parts.push(`${shadow.xOffset}${shadow.unit}`, `${shadow.yOffset}${shadow.unit}`);
101
+ if (shadow.blurRadius !== undefined) {
102
+ parts.push(`${shadow.blurRadius}${shadow.unit}`);
75
103
  }
76
- }
77
- /**
78
- * The maximum range of the box shadow.
79
- * @default 25
80
- */
81
- maxRange = 25;
82
- change = new EventEmitter();
83
- isDisabled = false;
84
- isDragging = false;
85
- value = { x: 0, y: 0 };
86
- x = 0;
87
- y = 0;
88
- blur = 0;
89
- spread = 0;
90
- color = 'black';
91
- line = { x1: 0, y1: 0, x2: 0, y2: 0 };
92
- center = { x: 0, y: 0 };
104
+ if (shadow.spreadRadius !== undefined) {
105
+ parts.push(`${shadow.spreadRadius}${shadow.unit}`);
106
+ }
107
+ parts.push(shadow.color);
108
+ return parts.join(' ');
109
+ })
110
+ .join(', ');
111
+ }
112
+ // Example usage:
113
+ /*
114
+ const css = "10px 20px 5px 0px rgba(0, 0, 0, 0.5), inset -10px -20px 10px #ff0000";
115
+ const parsed = parseBoxShadow(css);
116
+ console.log(parsed);
117
+ // Output: [
118
+ // { xOffset: 10, yOffset: 20, blurRadius: 5, spreadRadius: 0, color: "rgba(0, 0, 0, 0.5)", unit: "px" },
119
+ // { inset: true, xOffset: -10, yOffset: -20, blurRadius: 10, color: "#ff0000", unit: "px" }
120
+ // ]
121
+ const cssString = formatBoxShadowToCSS(parsed);
122
+ console.log(cssString);
123
+ // Output: "10px 20px 5px 0px rgba(0, 0, 0, 0.5), inset -10px -20px 10px #ff0000"
124
+ */
125
+
126
+ class NgxShadowControl {
127
+ maxRange = input(25, /* @ts-ignore */
128
+ ...(ngDevMode ? [{ debugName: "maxRange" }] : /* istanbul ignore next */ []));
129
+ selectedShadow = model.required(/* @ts-ignore */
130
+ ...(ngDevMode ? [{ debugName: "selectedShadow" }] : /* istanbul ignore next */ []));
131
+ _previousCssValue = '';
132
+ shadowChange = output();
93
133
  padRect;
94
- thumbRect;
95
- _onChange = (value) => { };
96
- _onTouched = () => { };
97
- _onValidateChange = () => { };
98
- stopDrag;
134
+ flashlightRect;
135
+ center = { x: 0, y: 0 };
136
+ x = signal(0, /* @ts-ignore */
137
+ ...(ngDevMode ? [{ debugName: "x" }] : /* istanbul ignore next */ []));
138
+ y = signal(0, /* @ts-ignore */
139
+ ...(ngDevMode ? [{ debugName: "y" }] : /* istanbul ignore next */ []));
140
+ isDragging = false;
99
141
  pad;
100
- thumb;
101
- browserService = inject(BrowserService);
102
- constructor(cd) {
103
- this.cd = cd;
104
- }
105
- ngOnInit() { }
106
- ngAfterViewInit() {
107
- this.updateRects();
142
+ flashlight;
143
+ radius = 0;
144
+ ngOnInit() {
145
+ this.setXyFromShadow(this.selectedShadow());
146
+ this._previousCssValue = this.selectedShadow().cssValue;
108
147
  }
109
- ngOnDestroy() {
110
- this.stopDrag?.();
111
- }
112
- registerOnChange(fn) {
113
- this._onChange = fn;
114
- }
115
- registerOnTouched(fn) {
116
- this._onTouched = fn;
117
- }
118
- setDisabledState(disabled) {
119
- this.isDisabled = disabled;
120
- }
121
- registerOnValidatorChange(fn) {
122
- this._onValidateChange = fn;
123
- }
124
- validate(control) {
125
- return null;
126
- }
127
- writeValue(value) {
128
- this.resetPosition();
129
- if (value) {
130
- const boxShadow = parseBoxShadowToPx(value);
131
- // console.log(boxShadow);
132
- if (boxShadow) {
133
- this.value = { x: boxShadow.offsetX, y: boxShadow.offsetY };
134
- this.blur = boxShadow.blurRadius;
135
- this.spread = boxShadow.spreadRadius;
136
- this.color = boxShadow.color;
137
- this.convertValueToPosition(boxShadow.offsetX, boxShadow.offsetY);
138
- }
139
- }
148
+ onPadClick(ev) {
149
+ const position = getOffsetPosition(ev, this.pad.nativeElement);
150
+ this.isDragging = true;
151
+ this.updatePosition(position);
140
152
  }
141
153
  dragStart(ev) {
142
154
  ev.stopPropagation();
143
155
  ev.preventDefault();
156
+ this.updateContainerDimensions();
144
157
  this.isDragging = true;
145
- this.updatePosition(ev);
146
- this.updateRects();
147
- this.stopDrag?.();
148
- this.stopDrag = startDragSession({
149
- onMove: (moveEv) => this.updatePosition(moveEv),
150
- onEnd: () => {
151
- this.isDragging = false;
152
- this.stopDrag = undefined;
153
- this.cd.markForCheck();
154
- },
155
- });
156
- }
157
- updateRects() {
158
- this.padRect = this.pad.nativeElement.getBoundingClientRect();
159
- this.thumbRect = this.thumb.nativeElement.getBoundingClientRect();
160
- }
161
- resetPosition() {
162
- if (!this.padRect || !this.thumbRect)
163
- this.updateRects();
164
- this.center = { x: this.padRect.width / 2, y: this.padRect.height / 2 };
165
- this.x = this.center.x - this.thumbRect.width / 2;
166
- this.y = this.center.y - this.thumbRect.height / 2;
167
- this.line = { x1: this.center.x, y1: this.center.y, x2: this.center.x, y2: this.center.y };
168
- this.cd.detectChanges();
158
+ const position = getOffsetPosition(ev, this.pad.nativeElement);
159
+ this.updatePosition(position);
169
160
  }
170
- onResize() {
171
- this.writeValue(this.value);
161
+ onDragEnd(ev) {
162
+ this.isDragging = false;
172
163
  }
173
- updatePosition(ev) {
164
+ onMouseMove(ev) {
174
165
  if (!this.isDragging)
175
166
  return;
176
- if (!this.padRect || !this.thumbRect)
177
- this.updateRects();
178
167
  const position = getOffsetPosition(ev, this.pad.nativeElement);
168
+ this.updatePosition(position);
169
+ }
170
+ updatePosition(position) {
179
171
  const padRec = this.padRect;
180
- const thumbRec = this.thumbRect;
181
- const minX = thumbRec.width / 2;
182
- const maxX = padRec.width - thumbRec.width / 2;
183
- const minY = thumbRec.height / 2;
184
- const maxY = padRec.height - thumbRec.height / 2;
172
+ const flashlightRec = this.flashlightRect;
173
+ const centerX = this.center.x;
174
+ const centerY = this.center.y;
175
+ const dx = position.x - centerX;
176
+ const dy = position.y - centerY;
177
+ // زاویه
178
+ const angleRad = Math.atan2(dy, dx);
179
+ const minX = flashlightRec.width / 2;
180
+ const maxX = padRec.width - flashlightRec.width / 2;
181
+ const minY = flashlightRec.height / 2;
182
+ const maxY = padRec.height - flashlightRec.height / 2;
185
183
  const clampedX = Math.max(minX, Math.min(position.x, maxX));
186
184
  const clampedY = Math.max(minY, Math.min(position.y, maxY));
187
185
  // فقط یکبار از وسط اصلاح کن
188
- this.x = clampedX - thumbRec.width / 2;
189
- this.y = clampedY - thumbRec.height / 2;
190
- this.line = {
191
- x1: this.center.x,
192
- y1: this.center.y,
193
- x2: this.x + thumbRec.width / 2,
194
- y2: this.y + thumbRec.height / 2,
195
- };
196
- this.setValueByPosition(thumbRec, padRec);
197
- this.cd.markForCheck();
198
- }
199
- setValueByPosition(thumbRec, padRec) {
200
- const padCenterX = (padRec.width - thumbRec.width) / 2;
201
- const padCenterY = (padRec.height - thumbRec.height) / 2;
202
- // فاصله thumb از مرکز
203
- const dx = this.x - padCenterX;
204
- const dy = this.y - padCenterY;
205
- // مقیاس تبدیل به -50 تا +50 (یا هرچقدر بخوای)
206
- const halfRangeX = (padRec.width - thumbRec.width) / 2;
207
- const halfRangeY = (padRec.height - thumbRec.height) / 2;
208
- let valueX = (dx / halfRangeX) * this.maxRange; // -50 تا +50
209
- let valueY = (dy / halfRangeY) * this.maxRange;
210
- // رُند کردن
211
- valueX = Math.round(valueX);
212
- valueY = Math.round(valueY);
213
- // محدود کردن به -50 تا +50 یا هر مقدار دلخواه
214
- valueX = Math.min(Math.max(valueX, -this.maxRange), this.maxRange);
215
- valueY = Math.min(Math.max(valueY, -this.maxRange), this.maxRange);
216
- const newValue = { x: valueX, y: valueY };
217
- if (!this.value || this.value.x !== valueX || this.value.y !== valueY) {
218
- this.value = newValue;
219
- this.onChangeData();
186
+ this.x.set(clampedX - flashlightRec.width / 2);
187
+ this.y.set(clampedY - flashlightRec.height / 2);
188
+ // ✅ ولی مقدار واقعی shadow رو از موقعیت موس (dx, dy) بگیر
189
+ const halfRangeX = (padRec.width - flashlightRec.width) / 2;
190
+ const halfRangeY = (padRec.height - flashlightRec.height) / 2;
191
+ let valueX = (-dx / halfRangeX) * this.maxRange();
192
+ let valueY = (-dy / halfRangeY) * this.maxRange();
193
+ valueX = Math.round(Math.min(Math.max(valueX, -this.maxRange()), this.maxRange()));
194
+ valueY = Math.round(Math.min(Math.max(valueY, -this.maxRange()), this.maxRange()));
195
+ // چرخش چراغ قوه
196
+ const angleDeg = angleRad * (180 / Math.PI);
197
+ if (this.flashlight.nativeElement) {
198
+ this.flashlight.nativeElement.style.transform = `rotate(${angleDeg + 180}deg)`;
220
199
  }
200
+ // آپدیت shadow
201
+ this.selectedShadow.set({
202
+ ...this.selectedShadow(),
203
+ xOffset: valueX,
204
+ yOffset: valueY,
205
+ });
206
+ this.updateShadow(this.selectedShadow());
207
+ }
208
+ updateContainerDimensions() {
209
+ setTimeout(() => {
210
+ if (!this.pad)
211
+ return;
212
+ this.padRect = this.pad.nativeElement.getBoundingClientRect();
213
+ this.flashlightRect = this.flashlight.nativeElement.getBoundingClientRect();
214
+ this.center = { x: this.padRect.width / 2, y: this.padRect.height / 2 };
215
+ this.radius =
216
+ Math.min(this.padRect.width, this.padRect.height) / 2 - this.flashlightRect.width / 2;
217
+ this.x.set(0); // Reset to center
218
+ this.y.set(0);
219
+ });
221
220
  }
222
- onChangeValue() {
223
- this.convertValueToPosition(this.value.x, this.value.y);
224
- this.onChangeData();
225
- }
226
- convertValueToPosition(offsetX, offsetY) {
227
- if (!this.padRect || !this.thumbRect)
228
- this.updateRects();
229
- // موقعیت پیشنهادی بر اساس offset
230
- let proposedX = this.padRect.width / 2 + offsetX - this.thumbRect.width / 2;
231
- let proposedY = this.padRect.height / 2 + offsetY - this.thumbRect.height / 2;
232
- // محدود کردن (clamp) تا خارج از pad نره
233
- const minX = 0;
234
- const maxX = this.padRect.width - this.thumbRect.width;
235
- const minY = 0;
236
- const maxY = this.padRect.height - this.thumbRect.height;
237
- this.x = Math.min(Math.max(proposedX, minX), maxX);
238
- this.y = Math.min(Math.max(proposedY, minY), maxY);
239
- // رسم خط راهنما از مرکز به thumb
240
- this.line = {
241
- x1: this.center.x,
242
- y1: this.center.y,
243
- x2: this.x + this.thumbRect.width / 2,
244
- y2: this.y + this.thumbRect.height / 2,
245
- };
246
- this.cd.detectChanges();
221
+ updateShadow(updatedShadow) {
222
+ this.selectedShadow().cssValue = formatBoxShadowToCSS([this.selectedShadow()]);
223
+ this.setXyFromShadow(this.selectedShadow());
224
+ if (this._previousCssValue != this.selectedShadow().cssValue) {
225
+ this.shadowChange.emit(this.selectedShadow());
226
+ }
247
227
  }
248
- onChangeData() {
249
- const boxShadow = stringifyBoxShadow({
250
- inset: false,
251
- offsetX: this.value.x,
252
- offsetY: this.value.y,
253
- blurRadius: this.blur,
254
- spreadRadius: this.spread,
255
- color: this.color,
228
+ setXyFromShadow(item) {
229
+ this.updateContainerDimensions();
230
+ setTimeout(() => {
231
+ const padRec = this.padRect;
232
+ const flashlightRec = this.flashlightRect;
233
+ const centerX = this.center.x;
234
+ const centerY = this.center.y;
235
+ const halfRangeX = (padRec.width - flashlightRec.width) / 2;
236
+ const halfRangeY = (padRec.height - flashlightRec.height) / 2;
237
+ // معکوس فرمول برای به‌دست آوردن dx , dy
238
+ const dx = -(item.xOffset / this.maxRange()) * halfRangeX;
239
+ const dy = -(item.yOffset / this.maxRange()) * halfRangeY;
240
+ // موقعیت واقعی چراغ‌قوه
241
+ const posX = centerX + dx;
242
+ const posY = centerY + dy;
243
+ this.x.set(posX - flashlightRec.width / 2);
244
+ this.y.set(posY - flashlightRec.height / 2);
245
+ // زاویه چراغ‌قوه
246
+ const angleRad = Math.atan2(dy, dx);
247
+ const angleDeg = angleRad * (180 / Math.PI);
248
+ if (this.flashlight.nativeElement) {
249
+ this.flashlight.nativeElement.style.transform = `rotate(${angleDeg + 180}deg)`;
250
+ }
256
251
  });
257
- this._onChange(boxShadow);
258
- this.change.emit(boxShadow);
259
- }
260
- stopPropagation(ev) {
261
- ev.stopPropagation();
262
252
  }
263
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: NgxBoxShadowComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
264
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.4", type: NgxBoxShadowComponent, isStandalone: true, selector: "ngx-box-shadow", inputs: { setTheme: ["theme", "setTheme"], maxRange: "maxRange" }, outputs: { change: "change" }, host: { listeners: { "window:resize": "onResize()" }, properties: { "class.dark": "theme==\"dark\"" } }, providers: [
265
- {
266
- provide: NG_VALUE_ACCESSOR,
267
- useExisting: forwardRef(() => NgxBoxShadowComponent),
268
- multi: true,
269
- },
270
- {
271
- provide: NG_VALIDATORS,
272
- multi: true,
273
- useExisting: NgxBoxShadowComponent,
274
- },
275
- ], viewQueries: [{ propertyName: "pad", first: true, predicate: ["pad"], descendants: true, static: true }, { propertyName: "thumb", first: true, predicate: ["thumb"], descendants: true, static: true }], ngImport: i0, template: "<div class=\"ngx-box-shadow-container\" (click)=\"stopPropagation($event)\">\n <div class=\"pad-container\" #pad>\n <svg viewBox=\"0 0 100 100\" xmlns=\"http://www.w3.org/2000/svg\">\n <line\n [attr.x1]=\"line.x1\"\n [attr.y1]=\"line.y1\"\n [attr.x2]=\"line.x2\"\n [attr.y2]=\"line.y2\"\n stroke=\"blue\"\n stroke-width=\"2\" />\n </svg>\n <div\n class=\"thumb\"\n #thumb\n [style.left.px]=\"x\"\n [style.top.px]=\"y\"\n (mousedown)=\"dragStart($event)\"\n (touchstart)=\"dragStart($event)\"></div>\n </div>\n\n <div class=\"ngx-settings\">\n <div class=\"ngx-setting-item\">\n <div class=\"ngx-row\">\n <span>Offset X</span>\n <input\n type=\"number\"\n id=\"offsetX\"\n [(ngModel)]=\"value.x\"\n name=\"offsetX\"\n (ngModelChange)=\"onChangeValue()\" />\n </div>\n <input\n type=\"range\"\n id=\"offsetX\"\n [(ngModel)]=\"value.x\"\n name=\"rangeOffsetX\"\n (ngModelChange)=\"onChangeValue()\"\n step=\"1\"\n [min]=\"-maxRange\"\n [max]=\"maxRange\" />\n </div>\n <div class=\"ngx-setting-item\">\n <div class=\"ngx-row\">\n <span>Offset Y</span>\n <input\n type=\"number\"\n id=\"offsetY\"\n [(ngModel)]=\"value.y\"\n name=\"offsetY\"\n (ngModelChange)=\"onChangeValue()\" />\n </div>\n <input\n type=\"range\"\n id=\"offsetY\"\n [(ngModel)]=\"value.y\"\n name=\"rangeOffsetY\"\n (ngModelChange)=\"onChangeValue()\"\n step=\"1\"\n [min]=\"-maxRange\"\n [max]=\"maxRange\" />\n </div>\n <div class=\"ngx-setting-item\">\n <div class=\"ngx-row\">\n <span>Blur</span>\n <input\n type=\"number\"\n id=\"blur\"\n [(ngModel)]=\"blur\"\n name=\"blur\"\n (ngModelChange)=\"onChangeValue()\" />\n </div>\n <input\n type=\"range\"\n id=\"blur\"\n [(ngModel)]=\"blur\"\n name=\"rangeBlur\"\n (ngModelChange)=\"onChangeValue()\"\n step=\"1\" />\n </div>\n <div class=\"ngx-setting-item\">\n <div class=\"ngx-row\">\n <span>Spread</span>\n <input\n type=\"number\"\n id=\"spread\"\n [(ngModel)]=\"spread\"\n name=\"spread\"\n (ngModelChange)=\"onChangeValue()\" />\n </div>\n <input\n type=\"range\"\n id=\"spread\"\n [(ngModel)]=\"spread\"\n name=\"rangeSpread\"\n (ngModelChange)=\"onChangeValue()\"\n step=\"1\" />\n </div>\n <div class=\"ngx-setting-item\">\n <div class=\"ngx-row\">\n <span>color</span>\n <input\n type=\"text\"\n readonly\n id=\"color\"\n [(ngModel)]=\"color\"\n name=\"color\"\n ngxInputColor\n [simpleMode]=\"true\"\n (ngModelChange)=\"onChangeData()\"\n autocomplete=\"off\" />\n </div>\n </div>\n </div>\n</div>\n", styles: [".ngx-box-shadow-container{width:180px;max-width:100%;border-radius:15px;background-color:#fff;overflow:hidden;direction:ltr;padding:12px;border:1px rgba(134,134,134,.3490196078) solid;box-shadow:0 0 20px #7a7a7a21}.ngx-box-shadow-container *{box-sizing:border-box}.pad-container{position:relative;width:100px;height:100px;border:1px #545454 solid;box-sizing:border-box;direction:ltr;border-radius:3px}.pad-container:after,.pad-container:before{content:\"\";position:absolute;border:1px rgba(145,145,145,.4117647059) solid}.pad-container:after{width:100%;top:calc(50% - 1px);left:0}.pad-container:before{height:100%;top:0;left:calc(50% - 1px)}.pad-container .thumb{box-shadow:inset 0 0 0 2px #fff;width:15px;height:15px;display:block;border-radius:10px;position:absolute;cursor:pointer;background:#00f}.ngx-settings .ngx-row{display:flex;align-items:flex-end;justify-content:space-between}.ngx-settings input:not([type=range]){width:46px;border:none;border:1px solid rgba(145,145,145,.4117647059);padding:2px 4px;border-radius:5px;background-color:transparent;color:#000;font-size:14px;font-weight:500;text-align:center;direction:ltr}.ngx-settings input:not([type=range]):focus{outline:none;border:1px solid #09218d}.ngx-settings input[type=range]{width:100%}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NumberValueAccessor, selector: "input[type=number]:not([ngNoCva])[formControlName],input[type=number]:not([ngNoCva])[formControl],input[type=number]:not([ngNoCva])[ngModel]" }, { kind: "directive", type: i1.RangeValueAccessor, selector: "input[type=range]:not([ngNoCva])[formControlName],input[type=range]:not([ngNoCva])[formControl],input[type=range]:not([ngNoCva])[ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: NgxInputColor, selector: "[ngxInputColor]", inputs: ["setInputBackgroundColor", "defaultInspector", "simpleMode", "outputType", "theme", "useAlphaChannel", "ngxInputColor"], outputs: ["change"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
253
+ close() { }
254
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: NgxShadowControl, deps: [], target: i0.ɵɵFactoryTarget.Component });
255
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.4", type: NgxShadowControl, isStandalone: true, selector: "ngx-shadow-control", inputs: { maxRange: { classPropertyName: "maxRange", publicName: "maxRange", isSignal: true, isRequired: false, transformFunction: null }, selectedShadow: { classPropertyName: "selectedShadow", publicName: "selectedShadow", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { selectedShadow: "selectedShadowChange", shadowChange: "shadowChange" }, host: { listeners: { "document:mouseup": "onDragEnd($event)", "document:touchend": "onDragEnd($event)", "mousemove": "onMouseMove($event)", "touchmove": "onMouseMove($event)" } }, viewQueries: [{ propertyName: "pad", first: true, predicate: ["pad"], descendants: true }, { propertyName: "flashlight", first: true, predicate: ["flashlight"], descendants: true }], ngImport: i0, template: "<div class=\"ngx-shadow-control\">\n <div\n class=\"pad-container\"\n #pad\n (mousedown)=\"onPadClick($event)\"\n (touchstart)=\"onPadClick($event)\">\n <div class=\"card-sample\" [style.boxShadow]=\"selectedShadow().cssValue\"></div>\n <svg\n class=\"flashlight-svg\"\n viewBox=\"0 0 640 512\"\n xmlns=\"http://www.w3.org/2000/svg\"\n #flashlight\n [style.left.px]=\"x()\"\n [style.top.px]=\"y()\"\n (mousedown)=\"dragStart($event)\"\n (touchstart)=\"dragStart($event)\">\n <defs>\n <style>\n .fa-secondary {\n opacity: 0.4;\n }\n </style>\n </defs>\n <path\n class=\"fa-primary\"\n d=\"M607.1 96h-32v320h32c17.62 0 32-14.38 32-32V128C639.1 110.4 625.6 96 607.1 96zM287.1 224h-32c-17.62 0-32 14.38-32 32s14.38 32 32 32h32c17.62 0 32-14.38 32-32S305.6 224 287.1 224z\" />\n <path\n class=\"fa-secondary\"\n d=\"M400.1 149.2L383.1 160H31.1c-17.62 0-32 14.38-32 32v128c0 17.62 14.38 32 32 32h352l16.12 10.75C443.2 391.5 511.1 416 575.1 416V96C511.1 96 443.2 120.5 400.1 149.2zM287.1 288h-32c-17.62 0-32-14.38-32-32s14.38-32 32-32h32c17.62 0 32 14.38 32 32S305.6 288 287.1 288z\" />\n </svg>\n </div>\n <div class=\"pi-btn-group\" role=\"group\">\n <input\n type=\"radio\"\n class=\"btn-check\"\n name=\"showside\"\n id=\"SHoutside\"\n autocomplete=\"off\"\n [(ngModel)]=\"selectedShadow().inset\"\n (ngModelChange)=\"updateShadow({ inset: selectedShadow().inset })\"\n [value]=\"false\" />\n <label class=\"button\" for=\"SHoutside\" title=\"Outside\">Outside</label>\n <input\n type=\"radio\"\n class=\"btn-check\"\n name=\"showside\"\n id=\"SHinside\"\n autocomplete=\"off\"\n [(ngModel)]=\"selectedShadow().inset\"\n (ngModelChange)=\"updateShadow({ inset: selectedShadow().inset })\"\n [value]=\"true\" />\n <label class=\"button\" for=\"SHinside\" title=\"Inside\">Inside</label>\n </div>\n <div class=\"shadow-item\">\n <table>\n <tr>\n <th>\n <span>X</span>\n </th>\n <td>\n <div class=\"d-flex\">\n <input\n type=\"range\"\n [min]=\"-maxRange()\"\n [max]=\"maxRange()\"\n [(ngModel)]=\"selectedShadow().xOffset\"\n (ngModelChange)=\"updateShadow({ xOffset: selectedShadow().xOffset })\" />\n <input\n type=\"number\"\n [min]=\"-maxRange()\"\n [max]=\"maxRange()\"\n [(ngModel)]=\"selectedShadow().xOffset\"\n (ngModelChange)=\"updateShadow({ xOffset: selectedShadow().xOffset })\" />\n </div>\n </td>\n </tr>\n <tr>\n <th>\n <span>Y</span>\n </th>\n <td>\n <div class=\"d-flex\">\n <input\n type=\"range\"\n [min]=\"-maxRange()\"\n [max]=\"maxRange()\"\n [(ngModel)]=\"selectedShadow().yOffset\"\n (ngModelChange)=\"updateShadow({ yOffset: selectedShadow().yOffset })\" />\n <input\n type=\"number\"\n [min]=\"-maxRange()\"\n [max]=\"maxRange()\"\n [(ngModel)]=\"selectedShadow().yOffset\"\n (ngModelChange)=\"updateShadow({ yOffset: selectedShadow().yOffset })\" />\n </div>\n </td>\n </tr>\n <tr>\n <th>\n <span>Blur</span>\n </th>\n <td>\n <div class=\"d-flex\">\n <input\n type=\"range\"\n [min]=\"0\"\n [max]=\"maxRange()\"\n [(ngModel)]=\"selectedShadow().blurRadius\"\n min=\"0\"\n (ngModelChange)=\"updateShadow({ blurRadius: selectedShadow().blurRadius })\" />\n <input\n type=\"number\"\n [min]=\"0\"\n [max]=\"maxRange()\"\n [(ngModel)]=\"selectedShadow().blurRadius\"\n min=\"0\"\n (ngModelChange)=\"updateShadow({ blurRadius: selectedShadow().blurRadius })\" />\n </div>\n </td>\n </tr>\n <tr>\n <th>\n <span>Spread</span>\n </th>\n <td>\n <div class=\"d-flex\">\n <input\n type=\"range\"\n [min]=\"0\"\n [max]=\"maxRange()\"\n [(ngModel)]=\"selectedShadow().spreadRadius\"\n (ngModelChange)=\"updateShadow({ spreadRadius: selectedShadow().spreadRadius })\" />\n <input\n type=\"number\"\n [min]=\"0\"\n [max]=\"maxRange()\"\n [(ngModel)]=\"selectedShadow().spreadRadius\"\n (ngModelChange)=\"updateShadow({ spreadRadius: selectedShadow().spreadRadius })\" />\n </div>\n </td>\n </tr>\n <tr>\n <th>\n <span>Color</span>\n </th>\n <td>\n <input\n type=\"text\"\n [(ngModel)]=\"selectedShadow().color\"\n (ngModelChange)=\"updateShadow({ color: selectedShadow().color })\"\n ngxInputColor\n [simpleMode]=\"true\" />\n </td>\n </tr>\n </table>\n </div>\n</div>\n", styles: [":host{--ngx-color-bg: light-dark(#fff, #222);--ngx-color-text: light-dark(#000, #fff)}.ngx-shadow-control{width:270px;max-width:100%;overflow:hidden;direction:ltr;font-family:arial,tahoma;border:1px rgba(134,134,134,.3490196078) solid;background:var(--ngx-color-bg);color:var(--ngx-color-text)}.card-sample{border-radius:5px;width:50px;height:50px;background-color:#fff;z-index:1;border:1px #bbbbbb solid}.pad-container{background:#fff;position:relative;width:100%;height:200px;border:1px #545454 solid;box-sizing:border-box;direction:ltr;border-radius:3px;display:flex;align-items:center;justify-content:center}.pad-container:after,.pad-container:before{content:\"\";position:absolute;border:1px rgba(100,100,100,.1490196078) dotted}.pad-container:after{width:100%;top:calc(50% - 1px);left:0}.pad-container:before{height:100%;top:0;left:calc(50% - 1px)}.pad-container .thumb{box-shadow:inset 0 0 0 2px #fff;width:15px;height:15px;display:block;border-radius:10px;position:absolute;cursor:pointer;background:#00f}.flashlight-svg{width:24px;position:absolute;transform-origin:center center;z-index:10;fill:#ff6a00}.container{position:relative;width:300px;height:300px;background:#fff;border:2px solid #333;border-radius:8px;margin:50px auto;transition:box-shadow .2s ease}.flashlight{position:absolute;width:24px;height:24px;color:gold;transform:translate(-50%,-50%);pointer-events:none}table{width:100%;table-layout:fixed}table th{width:60px;font-size:12px}i,button{color:inherit}input:not([type=range]){width:68px;background:#4d4d4d;border:none;border-radius:3px;color:inherit;padding:4px}input[type=range]{flex:auto;appearance:none;-webkit-appearance:none;width:auto;height:4px;border-radius:5px;background-color:#696969;outline:none;margin:20px 2px 0}input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;width:5px;height:20px;border-radius:2px;background-color:#1741ff;position:relative}.pi-btn-group{background-color:var(--color-bg-secondary, #383838);border:1px solid var(--color-bg-secondary, #383838);border-radius:var(--radius-medium, .3125rem);color:var(--fgColor)}.pi-btn-group button,.pi-btn-group .button{display:inline-block;padding:6px 10px;line-height:1;min-width:40px;border-radius:5px}.pi-btn-group button:last-child,.pi-btn-group .button:last-child{border-right:none}.pi-btn-group button.active,.pi-btn-group .button.active{background:#151515;border:none}.pi-btn-group input{display:none}.pi-btn-group label{color:inherit}.pi-btn-group i{font-weight:400;color:inherit}.pi-btn-group .btn-check:checked+.button{background:#151515;border:none}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NumberValueAccessor, selector: "input[type=number]:not([ngNoCva])[formControlName],input[type=number]:not([ngNoCva])[formControl],input[type=number]:not([ngNoCva])[ngModel]" }, { kind: "directive", type: i1.RangeValueAccessor, selector: "input[type=range]:not([ngNoCva])[formControlName],input[type=range]:not([ngNoCva])[formControl],input[type=range]:not([ngNoCva])[ngModel]" }, { kind: "directive", type: i1.RadioControlValueAccessor, selector: "input[type=radio]:not([ngNoCva])[formControlName],input[type=radio]:not([ngNoCva])[formControl],input[type=radio]:not([ngNoCva])[ngModel]", inputs: ["name", "formControlName", "value"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: NgxInputColor, selector: "[ngxInputColor]", inputs: ["setInputBackgroundColor", "simpleMode", "outputType", "defaultInspector", "useAlphaChannel", "showPresets", "presetColors", "ngxInputColor"], outputs: ["defaultInspectorChange", "colorChange", "change"], exportAs: ["ngxInputColor"] }] });
276
256
  }
277
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: NgxBoxShadowComponent, decorators: [{
257
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: NgxShadowControl, decorators: [{
278
258
  type: Component,
279
- args: [{ selector: 'ngx-box-shadow', changeDetection: ChangeDetectionStrategy.OnPush, providers: [
280
- {
281
- provide: NG_VALUE_ACCESSOR,
282
- useExisting: forwardRef(() => NgxBoxShadowComponent),
283
- multi: true,
284
- },
285
- {
286
- provide: NG_VALIDATORS,
287
- multi: true,
288
- useExisting: NgxBoxShadowComponent,
289
- },
290
- ], imports: [FormsModule, NgxInputColor], host: {
291
- '[class.dark]': 'theme=="dark"',
292
- }, template: "<div class=\"ngx-box-shadow-container\" (click)=\"stopPropagation($event)\">\n <div class=\"pad-container\" #pad>\n <svg viewBox=\"0 0 100 100\" xmlns=\"http://www.w3.org/2000/svg\">\n <line\n [attr.x1]=\"line.x1\"\n [attr.y1]=\"line.y1\"\n [attr.x2]=\"line.x2\"\n [attr.y2]=\"line.y2\"\n stroke=\"blue\"\n stroke-width=\"2\" />\n </svg>\n <div\n class=\"thumb\"\n #thumb\n [style.left.px]=\"x\"\n [style.top.px]=\"y\"\n (mousedown)=\"dragStart($event)\"\n (touchstart)=\"dragStart($event)\"></div>\n </div>\n\n <div class=\"ngx-settings\">\n <div class=\"ngx-setting-item\">\n <div class=\"ngx-row\">\n <span>Offset X</span>\n <input\n type=\"number\"\n id=\"offsetX\"\n [(ngModel)]=\"value.x\"\n name=\"offsetX\"\n (ngModelChange)=\"onChangeValue()\" />\n </div>\n <input\n type=\"range\"\n id=\"offsetX\"\n [(ngModel)]=\"value.x\"\n name=\"rangeOffsetX\"\n (ngModelChange)=\"onChangeValue()\"\n step=\"1\"\n [min]=\"-maxRange\"\n [max]=\"maxRange\" />\n </div>\n <div class=\"ngx-setting-item\">\n <div class=\"ngx-row\">\n <span>Offset Y</span>\n <input\n type=\"number\"\n id=\"offsetY\"\n [(ngModel)]=\"value.y\"\n name=\"offsetY\"\n (ngModelChange)=\"onChangeValue()\" />\n </div>\n <input\n type=\"range\"\n id=\"offsetY\"\n [(ngModel)]=\"value.y\"\n name=\"rangeOffsetY\"\n (ngModelChange)=\"onChangeValue()\"\n step=\"1\"\n [min]=\"-maxRange\"\n [max]=\"maxRange\" />\n </div>\n <div class=\"ngx-setting-item\">\n <div class=\"ngx-row\">\n <span>Blur</span>\n <input\n type=\"number\"\n id=\"blur\"\n [(ngModel)]=\"blur\"\n name=\"blur\"\n (ngModelChange)=\"onChangeValue()\" />\n </div>\n <input\n type=\"range\"\n id=\"blur\"\n [(ngModel)]=\"blur\"\n name=\"rangeBlur\"\n (ngModelChange)=\"onChangeValue()\"\n step=\"1\" />\n </div>\n <div class=\"ngx-setting-item\">\n <div class=\"ngx-row\">\n <span>Spread</span>\n <input\n type=\"number\"\n id=\"spread\"\n [(ngModel)]=\"spread\"\n name=\"spread\"\n (ngModelChange)=\"onChangeValue()\" />\n </div>\n <input\n type=\"range\"\n id=\"spread\"\n [(ngModel)]=\"spread\"\n name=\"rangeSpread\"\n (ngModelChange)=\"onChangeValue()\"\n step=\"1\" />\n </div>\n <div class=\"ngx-setting-item\">\n <div class=\"ngx-row\">\n <span>color</span>\n <input\n type=\"text\"\n readonly\n id=\"color\"\n [(ngModel)]=\"color\"\n name=\"color\"\n ngxInputColor\n [simpleMode]=\"true\"\n (ngModelChange)=\"onChangeData()\"\n autocomplete=\"off\" />\n </div>\n </div>\n </div>\n</div>\n", styles: [".ngx-box-shadow-container{width:180px;max-width:100%;border-radius:15px;background-color:#fff;overflow:hidden;direction:ltr;padding:12px;border:1px rgba(134,134,134,.3490196078) solid;box-shadow:0 0 20px #7a7a7a21}.ngx-box-shadow-container *{box-sizing:border-box}.pad-container{position:relative;width:100px;height:100px;border:1px #545454 solid;box-sizing:border-box;direction:ltr;border-radius:3px}.pad-container:after,.pad-container:before{content:\"\";position:absolute;border:1px rgba(145,145,145,.4117647059) solid}.pad-container:after{width:100%;top:calc(50% - 1px);left:0}.pad-container:before{height:100%;top:0;left:calc(50% - 1px)}.pad-container .thumb{box-shadow:inset 0 0 0 2px #fff;width:15px;height:15px;display:block;border-radius:10px;position:absolute;cursor:pointer;background:#00f}.ngx-settings .ngx-row{display:flex;align-items:flex-end;justify-content:space-between}.ngx-settings input:not([type=range]){width:46px;border:none;border:1px solid rgba(145,145,145,.4117647059);padding:2px 4px;border-radius:5px;background-color:transparent;color:#000;font-size:14px;font-weight:500;text-align:center;direction:ltr}.ngx-settings input:not([type=range]):focus{outline:none;border:1px solid #09218d}.ngx-settings input[type=range]{width:100%}\n"] }]
293
- }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { setTheme: [{
294
- type: Input,
295
- args: ['theme']
296
- }], maxRange: [{
297
- type: Input
298
- }], change: [{
299
- type: Output
300
- }], pad: [{
259
+ args: [{ selector: 'ngx-shadow-control', imports: [FormsModule, NgxInputColor], template: "<div class=\"ngx-shadow-control\">\n <div\n class=\"pad-container\"\n #pad\n (mousedown)=\"onPadClick($event)\"\n (touchstart)=\"onPadClick($event)\">\n <div class=\"card-sample\" [style.boxShadow]=\"selectedShadow().cssValue\"></div>\n <svg\n class=\"flashlight-svg\"\n viewBox=\"0 0 640 512\"\n xmlns=\"http://www.w3.org/2000/svg\"\n #flashlight\n [style.left.px]=\"x()\"\n [style.top.px]=\"y()\"\n (mousedown)=\"dragStart($event)\"\n (touchstart)=\"dragStart($event)\">\n <defs>\n <style>\n .fa-secondary {\n opacity: 0.4;\n }\n </style>\n </defs>\n <path\n class=\"fa-primary\"\n d=\"M607.1 96h-32v320h32c17.62 0 32-14.38 32-32V128C639.1 110.4 625.6 96 607.1 96zM287.1 224h-32c-17.62 0-32 14.38-32 32s14.38 32 32 32h32c17.62 0 32-14.38 32-32S305.6 224 287.1 224z\" />\n <path\n class=\"fa-secondary\"\n d=\"M400.1 149.2L383.1 160H31.1c-17.62 0-32 14.38-32 32v128c0 17.62 14.38 32 32 32h352l16.12 10.75C443.2 391.5 511.1 416 575.1 416V96C511.1 96 443.2 120.5 400.1 149.2zM287.1 288h-32c-17.62 0-32-14.38-32-32s14.38-32 32-32h32c17.62 0 32 14.38 32 32S305.6 288 287.1 288z\" />\n </svg>\n </div>\n <div class=\"pi-btn-group\" role=\"group\">\n <input\n type=\"radio\"\n class=\"btn-check\"\n name=\"showside\"\n id=\"SHoutside\"\n autocomplete=\"off\"\n [(ngModel)]=\"selectedShadow().inset\"\n (ngModelChange)=\"updateShadow({ inset: selectedShadow().inset })\"\n [value]=\"false\" />\n <label class=\"button\" for=\"SHoutside\" title=\"Outside\">Outside</label>\n <input\n type=\"radio\"\n class=\"btn-check\"\n name=\"showside\"\n id=\"SHinside\"\n autocomplete=\"off\"\n [(ngModel)]=\"selectedShadow().inset\"\n (ngModelChange)=\"updateShadow({ inset: selectedShadow().inset })\"\n [value]=\"true\" />\n <label class=\"button\" for=\"SHinside\" title=\"Inside\">Inside</label>\n </div>\n <div class=\"shadow-item\">\n <table>\n <tr>\n <th>\n <span>X</span>\n </th>\n <td>\n <div class=\"d-flex\">\n <input\n type=\"range\"\n [min]=\"-maxRange()\"\n [max]=\"maxRange()\"\n [(ngModel)]=\"selectedShadow().xOffset\"\n (ngModelChange)=\"updateShadow({ xOffset: selectedShadow().xOffset })\" />\n <input\n type=\"number\"\n [min]=\"-maxRange()\"\n [max]=\"maxRange()\"\n [(ngModel)]=\"selectedShadow().xOffset\"\n (ngModelChange)=\"updateShadow({ xOffset: selectedShadow().xOffset })\" />\n </div>\n </td>\n </tr>\n <tr>\n <th>\n <span>Y</span>\n </th>\n <td>\n <div class=\"d-flex\">\n <input\n type=\"range\"\n [min]=\"-maxRange()\"\n [max]=\"maxRange()\"\n [(ngModel)]=\"selectedShadow().yOffset\"\n (ngModelChange)=\"updateShadow({ yOffset: selectedShadow().yOffset })\" />\n <input\n type=\"number\"\n [min]=\"-maxRange()\"\n [max]=\"maxRange()\"\n [(ngModel)]=\"selectedShadow().yOffset\"\n (ngModelChange)=\"updateShadow({ yOffset: selectedShadow().yOffset })\" />\n </div>\n </td>\n </tr>\n <tr>\n <th>\n <span>Blur</span>\n </th>\n <td>\n <div class=\"d-flex\">\n <input\n type=\"range\"\n [min]=\"0\"\n [max]=\"maxRange()\"\n [(ngModel)]=\"selectedShadow().blurRadius\"\n min=\"0\"\n (ngModelChange)=\"updateShadow({ blurRadius: selectedShadow().blurRadius })\" />\n <input\n type=\"number\"\n [min]=\"0\"\n [max]=\"maxRange()\"\n [(ngModel)]=\"selectedShadow().blurRadius\"\n min=\"0\"\n (ngModelChange)=\"updateShadow({ blurRadius: selectedShadow().blurRadius })\" />\n </div>\n </td>\n </tr>\n <tr>\n <th>\n <span>Spread</span>\n </th>\n <td>\n <div class=\"d-flex\">\n <input\n type=\"range\"\n [min]=\"0\"\n [max]=\"maxRange()\"\n [(ngModel)]=\"selectedShadow().spreadRadius\"\n (ngModelChange)=\"updateShadow({ spreadRadius: selectedShadow().spreadRadius })\" />\n <input\n type=\"number\"\n [min]=\"0\"\n [max]=\"maxRange()\"\n [(ngModel)]=\"selectedShadow().spreadRadius\"\n (ngModelChange)=\"updateShadow({ spreadRadius: selectedShadow().spreadRadius })\" />\n </div>\n </td>\n </tr>\n <tr>\n <th>\n <span>Color</span>\n </th>\n <td>\n <input\n type=\"text\"\n [(ngModel)]=\"selectedShadow().color\"\n (ngModelChange)=\"updateShadow({ color: selectedShadow().color })\"\n ngxInputColor\n [simpleMode]=\"true\" />\n </td>\n </tr>\n </table>\n </div>\n</div>\n", styles: [":host{--ngx-color-bg: light-dark(#fff, #222);--ngx-color-text: light-dark(#000, #fff)}.ngx-shadow-control{width:270px;max-width:100%;overflow:hidden;direction:ltr;font-family:arial,tahoma;border:1px rgba(134,134,134,.3490196078) solid;background:var(--ngx-color-bg);color:var(--ngx-color-text)}.card-sample{border-radius:5px;width:50px;height:50px;background-color:#fff;z-index:1;border:1px #bbbbbb solid}.pad-container{background:#fff;position:relative;width:100%;height:200px;border:1px #545454 solid;box-sizing:border-box;direction:ltr;border-radius:3px;display:flex;align-items:center;justify-content:center}.pad-container:after,.pad-container:before{content:\"\";position:absolute;border:1px rgba(100,100,100,.1490196078) dotted}.pad-container:after{width:100%;top:calc(50% - 1px);left:0}.pad-container:before{height:100%;top:0;left:calc(50% - 1px)}.pad-container .thumb{box-shadow:inset 0 0 0 2px #fff;width:15px;height:15px;display:block;border-radius:10px;position:absolute;cursor:pointer;background:#00f}.flashlight-svg{width:24px;position:absolute;transform-origin:center center;z-index:10;fill:#ff6a00}.container{position:relative;width:300px;height:300px;background:#fff;border:2px solid #333;border-radius:8px;margin:50px auto;transition:box-shadow .2s ease}.flashlight{position:absolute;width:24px;height:24px;color:gold;transform:translate(-50%,-50%);pointer-events:none}table{width:100%;table-layout:fixed}table th{width:60px;font-size:12px}i,button{color:inherit}input:not([type=range]){width:68px;background:#4d4d4d;border:none;border-radius:3px;color:inherit;padding:4px}input[type=range]{flex:auto;appearance:none;-webkit-appearance:none;width:auto;height:4px;border-radius:5px;background-color:#696969;outline:none;margin:20px 2px 0}input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;width:5px;height:20px;border-radius:2px;background-color:#1741ff;position:relative}.pi-btn-group{background-color:var(--color-bg-secondary, #383838);border:1px solid var(--color-bg-secondary, #383838);border-radius:var(--radius-medium, .3125rem);color:var(--fgColor)}.pi-btn-group button,.pi-btn-group .button{display:inline-block;padding:6px 10px;line-height:1;min-width:40px;border-radius:5px}.pi-btn-group button:last-child,.pi-btn-group .button:last-child{border-right:none}.pi-btn-group button.active,.pi-btn-group .button.active{background:#151515;border:none}.pi-btn-group input{display:none}.pi-btn-group label{color:inherit}.pi-btn-group i{font-weight:400;color:inherit}.pi-btn-group .btn-check:checked+.button{background:#151515;border:none}\n"] }]
260
+ }], propDecorators: { maxRange: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxRange", required: false }] }], selectedShadow: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedShadow", required: true }] }, { type: i0.Output, args: ["selectedShadowChange"] }], shadowChange: [{ type: i0.Output, args: ["shadowChange"] }], pad: [{
301
261
  type: ViewChild,
302
- args: ['pad', { static: true }]
303
- }], thumb: [{
262
+ args: ['pad', { static: false }]
263
+ }], flashlight: [{
304
264
  type: ViewChild,
305
- args: ['thumb', { static: true }]
306
- }], onResize: [{
265
+ args: ['flashlight', { static: false }]
266
+ }], onDragEnd: [{
267
+ type: HostListener,
268
+ args: ['document:mouseup', ['$event']]
269
+ }, {
270
+ type: HostListener,
271
+ args: ['document:touchend', ['$event']]
272
+ }], onMouseMove: [{
273
+ type: HostListener,
274
+ args: ['mousemove', ['$event']]
275
+ }, {
307
276
  type: HostListener,
308
- args: ['window:resize']
277
+ args: ['touchmove', ['$event']]
309
278
  }] } });
310
279
 
311
- class NgxInputBoxShadow {
312
- el;
313
- viewContainerRef;
314
- renderer;
315
- overlayService;
316
- setInputBackground = true;
317
- pickerRef;
318
- value = '';
319
- _onChange = (value) => { };
320
- _onTouched = () => { };
321
- _onValidateChange = () => { };
322
- constructor(el, viewContainerRef, renderer, overlayService) {
323
- this.el = el;
324
- this.viewContainerRef = viewContainerRef;
325
- this.renderer = renderer;
326
- this.overlayService = overlayService;
327
- }
328
- onClick(ev) {
329
- ev.stopPropagation();
330
- ev.preventDefault();
331
- this.toggleColorPicker();
332
- }
280
+ class NgxShadowBox {
281
+ maxRange = input(25, /* @ts-ignore */
282
+ ...(ngDevMode ? [{ debugName: "maxRange" }] : /* istanbul ignore next */ []));
283
+ shadowChange = output();
284
+ selectedIndex = signal(-1, /* @ts-ignore */
285
+ ...(ngDevMode ? [{ debugName: "selectedIndex" }] : /* istanbul ignore next */ []));
286
+ shadows = signal([], /* @ts-ignore */
287
+ ...(ngDevMode ? [{ debugName: "shadows" }] : /* istanbul ignore next */ []));
288
+ result = '';
289
+ doc = inject(DOCUMENT);
290
+ win = inject(WINDOW);
291
+ overlay = inject(OverlayService);
292
+ chdr = inject(ChangeDetectorRef);
293
+ isDisabled = false;
294
+ onChange = (_) => { };
295
+ onTouched = () => { };
333
296
  registerOnChange(fn) {
334
- this._onChange = fn;
297
+ this.onChange = fn;
335
298
  }
336
299
  registerOnTouched(fn) {
337
- this._onTouched = fn;
338
- }
339
- setDisabledState(disabled) {
340
- if (disabled) {
341
- this.renderer.setProperty(this.el.nativeElement, 'disabled', disabled);
342
- }
343
- else {
344
- this.renderer.removeAttribute(this.el.nativeElement, 'disabled');
345
- }
346
- }
347
- registerOnValidatorChange(fn) {
348
- this._onValidateChange = fn;
349
- }
350
- validate(control) {
351
- return null;
352
- }
353
- ngOnDestroy() {
354
- this.destroyPicker();
300
+ this.onTouched = fn;
355
301
  }
356
- writeValue(value) {
357
- this.value = value;
302
+ setDisabledState(isDisabled) {
303
+ this.isDisabled = isDisabled;
358
304
  }
359
- toggleColorPicker() {
360
- if (this.pickerRef) {
361
- this.destroyPicker();
305
+ constructor() { }
306
+ ngOnInit() { }
307
+ ngAfterViewInit() { }
308
+ writeValue(val) {
309
+ if (!val) {
310
+ this.shadows.set([]);
311
+ this.result = '';
362
312
  return;
363
313
  }
364
- this.pickerRef = this.overlayService.open({
365
- anchor: this.el.nativeElement,
366
- component: NgxBoxShadowComponent,
367
- viewContainerRef: this.viewContainerRef,
368
- alignment: 'start',
369
- placement: 'auto',
314
+ this.shadows.set(parseBoxShadow(val));
315
+ this.result = formatBoxShadowToCSS(this.shadows());
316
+ // if (val !== this.result) {
317
+ // this.update();
318
+ // }
319
+ }
320
+ addShadow(container) {
321
+ this.shadows.update((u) => [
322
+ ...u,
323
+ {
324
+ xOffset: 0,
325
+ yOffset: 0,
326
+ blurRadius: 10,
327
+ spreadRadius: 0,
328
+ color: 'rgba(0, 0, 0, 0.5)',
329
+ unit: 'px',
330
+ inset: false,
331
+ },
332
+ ]);
333
+ this.update();
334
+ setTimeout(() => {
335
+ container.scrollTop = container.scrollHeight;
336
+ }, 100);
337
+ }
338
+ setShadow(el, item, index) {
339
+ this.selectedIndex.set(index);
340
+ this.overlay.open({
341
+ component: NgxShadowControl,
342
+ anchor: el,
370
343
  configure: (instance, ref) => {
371
- instance.writeValue(this.value);
372
- instance.change.subscribe((c) => {
373
- this._onChange(c);
344
+ ref.componentRef?.setInput('maxRange', this.maxRange());
345
+ ref.componentRef?.setInput('selectedShadow', item);
346
+ instance.shadowChange.subscribe((v) => {
347
+ item = v;
348
+ this.shadows.update((shadows) => {
349
+ shadows[this.selectedIndex()] = item;
350
+ return shadows;
351
+ });
352
+ this.chdr.markForCheck();
353
+ this.update();
374
354
  });
375
- // instance.closed.subscribe(() => ref.close());
376
355
  },
377
356
  onClosed: () => {
378
- this.pickerRef = undefined;
357
+ this.selectedIndex.set(-1);
379
358
  },
380
359
  });
381
360
  }
382
- destroyPicker() {
383
- if (this.pickerRef) {
384
- this.pickerRef.close();
385
- this.pickerRef = undefined;
386
- }
361
+ removeShadow(ev, index) {
362
+ ev.stopPropagation();
363
+ this.shadows().splice(index, 1);
364
+ this.update();
365
+ }
366
+ update() {
367
+ this.result = formatBoxShadowToCSS(this.shadows());
368
+ this.shadows().forEach((m) => (m.cssValue = formatBoxShadowToCSS([m])));
369
+ this.onChange(this.result);
370
+ this.shadowChange.emit(this.result);
387
371
  }
388
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: NgxInputBoxShadow, deps: [{ token: i0.ElementRef }, { token: i0.ViewContainerRef }, { token: i0.Renderer2 }, { token: i1$1.OverlayService }], target: i0.ɵɵFactoryTarget.Directive });
389
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.4", type: NgxInputBoxShadow, isStandalone: true, selector: "[ngxInputBoxShadow]", inputs: { setInputBackground: "setInputBackground" }, host: { listeners: { "click": "onClick($event)" } }, providers: [
390
- { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => NgxInputBoxShadow), multi: true },
372
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: NgxShadowBox, deps: [], target: i0.ɵɵFactoryTarget.Component });
373
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.4", type: NgxShadowBox, isStandalone: true, selector: "ngx-box-shadow", inputs: { maxRange: { classPropertyName: "maxRange", publicName: "maxRange", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { shadowChange: "shadowChange" }, providers: [
391
374
  {
392
- provide: NG_VALIDATORS,
375
+ provide: NG_VALUE_ACCESSOR,
376
+ useExisting: forwardRef(() => NgxShadowBox),
393
377
  multi: true,
394
- useExisting: NgxInputBoxShadow,
395
378
  },
396
- ], ngImport: i0 });
379
+ ], ngImport: i0, template: "<div class=\"\">\n <button (click)=\"addShadow(list)\" type=\"button\" class=\"action-btn add-btn\">Add</button>\n</div>\n<div class=\"list-box\" #list>\n @for (item of shadows(); let i = $index; track i) {\n <button\n type=\"button\"\n class=\"list-item\"\n [class.active]=\"i == selectedIndex()\"\n #el\n (click)=\"setShadow(el, item, i)\">\n <span>{{ item.cssValue }}</span>\n <button (click)=\"removeShadow($event, i)\" type=\"button\" class=\"action-btn\">\n <svg fill=\"currentColor\" viewBox=\"0 0 320 512\">\n <path\n d=\"M315.3 411.3c-6.253 6.253-16.37 6.253-22.63 0L160 278.6l-132.7 132.7c-6.253 6.253-16.37 6.253-22.63 0c-6.253-6.253-6.253-16.37 0-22.63L137.4 256L4.69 123.3c-6.253-6.253-6.253-16.37 0-22.63c6.253-6.253 16.37-6.253 22.63 0L160 233.4l132.7-132.7c6.253-6.253 16.37-6.253 22.63 0c6.253 6.253 6.253 16.37 0 22.63L182.6 256l132.7 132.7C321.6 394.9 321.6 405.1 315.3 411.3z\" />\n </svg>\n </button>\n </button>\n }\n</div>\n", styles: [".list-box{max-width:320px;max-height:250px;overflow:auto;border-top:1px rgba(117,117,117,.1411764706) solid;display:flex;flex-direction:column;margin:15px 0}.list-box .list-item{all:unset;outline:none;display:flex;justify-content:space-between;align-items:center;padding:0 10px;line-height:1;font-size:10px;height:28px;overflow:hidden;border-bottom:1px rgba(74,91,115,.2588235294) solid;border-radius:5px}.list-box .list-item span{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.list-box .list-item.active{border:1px #005eff solid;background-color:#005eff}.action-btn{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;background:none;border:none;cursor:pointer;color:inherit;padding:4px;border-radius:6px;height:24px;background:light-dark(#efeff1,#2b2b33)}.action-btn svg{width:24px;height:100%}.action-btn:hover{background:light-dark(#e2e2e6,#34343d)}.add-btn{font-size:inherit;padding:5px 20px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
397
380
  }
398
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: NgxInputBoxShadow, decorators: [{
399
- type: Directive,
400
- args: [{
401
- selector: '[ngxInputBoxShadow]',
402
- providers: [
403
- { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => NgxInputBoxShadow), multi: true },
381
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: NgxShadowBox, decorators: [{
382
+ type: Component,
383
+ args: [{ selector: 'ngx-box-shadow', standalone: true, imports: [CommonModule, FormsModule], providers: [
404
384
  {
405
- provide: NG_VALIDATORS,
385
+ provide: NG_VALUE_ACCESSOR,
386
+ useExisting: forwardRef(() => NgxShadowBox),
406
387
  multi: true,
407
- useExisting: NgxInputBoxShadow,
408
388
  },
409
- ],
410
- }]
411
- }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.ViewContainerRef }, { type: i0.Renderer2 }, { type: i1$1.OverlayService }], propDecorators: { setInputBackground: [{
412
- type: Input
413
- }], onClick: [{
414
- type: HostListener,
415
- args: ['click', ['$event']]
416
- }] } });
389
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"\">\n <button (click)=\"addShadow(list)\" type=\"button\" class=\"action-btn add-btn\">Add</button>\n</div>\n<div class=\"list-box\" #list>\n @for (item of shadows(); let i = $index; track i) {\n <button\n type=\"button\"\n class=\"list-item\"\n [class.active]=\"i == selectedIndex()\"\n #el\n (click)=\"setShadow(el, item, i)\">\n <span>{{ item.cssValue }}</span>\n <button (click)=\"removeShadow($event, i)\" type=\"button\" class=\"action-btn\">\n <svg fill=\"currentColor\" viewBox=\"0 0 320 512\">\n <path\n d=\"M315.3 411.3c-6.253 6.253-16.37 6.253-22.63 0L160 278.6l-132.7 132.7c-6.253 6.253-16.37 6.253-22.63 0c-6.253-6.253-6.253-16.37 0-22.63L137.4 256L4.69 123.3c-6.253-6.253-6.253-16.37 0-22.63c6.253-6.253 16.37-6.253 22.63 0L160 233.4l132.7-132.7c6.253-6.253 16.37-6.253 22.63 0c6.253 6.253 6.253 16.37 0 22.63L182.6 256l132.7 132.7C321.6 394.9 321.6 405.1 315.3 411.3z\" />\n </svg>\n </button>\n </button>\n }\n</div>\n", styles: [".list-box{max-width:320px;max-height:250px;overflow:auto;border-top:1px rgba(117,117,117,.1411764706) solid;display:flex;flex-direction:column;margin:15px 0}.list-box .list-item{all:unset;outline:none;display:flex;justify-content:space-between;align-items:center;padding:0 10px;line-height:1;font-size:10px;height:28px;overflow:hidden;border-bottom:1px rgba(74,91,115,.2588235294) solid;border-radius:5px}.list-box .list-item span{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.list-box .list-item.active{border:1px #005eff solid;background-color:#005eff}.action-btn{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;background:none;border:none;cursor:pointer;color:inherit;padding:4px;border-radius:6px;height:24px;background:light-dark(#efeff1,#2b2b33)}.action-btn svg{width:24px;height:100%}.action-btn:hover{background:light-dark(#e2e2e6,#34343d)}.add-btn{font-size:inherit;padding:5px 20px}\n"] }]
390
+ }], ctorParameters: () => [], propDecorators: { maxRange: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxRange", required: false }] }], shadowChange: [{ type: i0.Output, args: ["shadowChange"] }] } });
417
391
 
418
392
  /**
419
393
  * Generated bundle index. Do not edit.
420
394
  */
421
395
 
422
- export { NgxBoxShadowComponent, NgxInputBoxShadow };
396
+ export { NgxShadowBox };
423
397
  //# sourceMappingURL=ngx-kit-box-shadow.mjs.map