@acorex/cdk 22.1.7 → 22.2.0-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/auto-follow-scroll/README.md +9 -0
  2. package/fesm2022/acorex-cdk-accordion.mjs +19 -19
  3. package/fesm2022/acorex-cdk-accordion.mjs.map +1 -1
  4. package/fesm2022/acorex-cdk-auto-follow-scroll.mjs +187 -0
  5. package/fesm2022/acorex-cdk-auto-follow-scroll.mjs.map +1 -0
  6. package/fesm2022/acorex-cdk-carousel.mjs +25 -7
  7. package/fesm2022/acorex-cdk-carousel.mjs.map +1 -1
  8. package/fesm2022/acorex-cdk-clipboard.mjs +6 -6
  9. package/fesm2022/acorex-cdk-clipboard.mjs.map +1 -1
  10. package/fesm2022/acorex-cdk-common.mjs +146 -92
  11. package/fesm2022/acorex-cdk-common.mjs.map +1 -1
  12. package/fesm2022/acorex-cdk-dom.mjs +3 -3
  13. package/fesm2022/acorex-cdk-dom.mjs.map +1 -1
  14. package/fesm2022/acorex-cdk-drag-drop.mjs +161 -69
  15. package/fesm2022/acorex-cdk-drag-drop.mjs.map +1 -1
  16. package/fesm2022/acorex-cdk-drawer.mjs +11 -11
  17. package/fesm2022/acorex-cdk-drawer.mjs.map +1 -1
  18. package/fesm2022/acorex-cdk-focus-trap.mjs +3 -3
  19. package/fesm2022/acorex-cdk-focus-trap.mjs.map +1 -1
  20. package/fesm2022/acorex-cdk-full-screen.mjs +26 -147
  21. package/fesm2022/acorex-cdk-full-screen.mjs.map +1 -1
  22. package/fesm2022/acorex-cdk-gesture.mjs +30 -4
  23. package/fesm2022/acorex-cdk-gesture.mjs.map +1 -1
  24. package/fesm2022/acorex-cdk-highlight.mjs +8 -78
  25. package/fesm2022/acorex-cdk-highlight.mjs.map +1 -1
  26. package/fesm2022/acorex-cdk-horizontal-scroll.mjs +27 -10
  27. package/fesm2022/acorex-cdk-horizontal-scroll.mjs.map +1 -1
  28. package/fesm2022/acorex-cdk-input-mask.mjs +3 -3
  29. package/fesm2022/acorex-cdk-input-mask.mjs.map +1 -1
  30. package/fesm2022/acorex-cdk-list-navigation.mjs +10 -10
  31. package/fesm2022/acorex-cdk-list-navigation.mjs.map +1 -1
  32. package/fesm2022/acorex-cdk-outline.mjs +277 -74
  33. package/fesm2022/acorex-cdk-outline.mjs.map +1 -1
  34. package/fesm2022/acorex-cdk-overlay.mjs +224 -21
  35. package/fesm2022/acorex-cdk-overlay.mjs.map +1 -1
  36. package/fesm2022/acorex-cdk-pan-view.mjs +3 -3
  37. package/fesm2022/acorex-cdk-pan-view.mjs.map +1 -1
  38. package/fesm2022/acorex-cdk-qrcode.mjs.map +1 -1
  39. package/fesm2022/acorex-cdk-resizable.mjs +483 -200
  40. package/fesm2022/acorex-cdk-resizable.mjs.map +1 -1
  41. package/fesm2022/acorex-cdk-selection.mjs +10 -10
  42. package/fesm2022/acorex-cdk-selection.mjs.map +1 -1
  43. package/fesm2022/acorex-cdk-shimmer.mjs +220 -0
  44. package/fesm2022/acorex-cdk-shimmer.mjs.map +1 -0
  45. package/fesm2022/acorex-cdk-sliding-item.mjs +3 -3
  46. package/fesm2022/acorex-cdk-sliding-item.mjs.map +1 -1
  47. package/fesm2022/acorex-cdk-sticky.mjs +3 -3
  48. package/fesm2022/acorex-cdk-sticky.mjs.map +1 -1
  49. package/fesm2022/acorex-cdk-uploader.mjs +9 -9
  50. package/fesm2022/acorex-cdk-uploader.mjs.map +1 -1
  51. package/fesm2022/acorex-cdk-viewport-guard.mjs +616 -0
  52. package/fesm2022/acorex-cdk-viewport-guard.mjs.map +1 -0
  53. package/fesm2022/acorex-cdk-virtual-scroll.mjs +10 -10
  54. package/fesm2022/acorex-cdk-virtual-scroll.mjs.map +1 -1
  55. package/fesm2022/acorex-cdk-wysiwyg.mjs +689 -37
  56. package/fesm2022/acorex-cdk-wysiwyg.mjs.map +1 -1
  57. package/fesm2022/acorex-cdk-z-index.mjs +3 -3
  58. package/fesm2022/acorex-cdk-z-index.mjs.map +1 -1
  59. package/fesm2022/acorex-cdk.mjs.map +1 -1
  60. package/package.json +23 -7
  61. package/shimmer/README.md +11 -0
  62. package/types/acorex-cdk-auto-follow-scroll.d.ts +72 -0
  63. package/types/acorex-cdk-carousel.d.ts +2 -0
  64. package/types/acorex-cdk-clipboard.d.ts +1 -1
  65. package/types/acorex-cdk-common.d.ts +36 -19
  66. package/types/acorex-cdk-drag-drop.d.ts +43 -17
  67. package/types/acorex-cdk-full-screen.d.ts +18 -43
  68. package/types/acorex-cdk-gesture.d.ts +11 -1
  69. package/types/acorex-cdk-highlight.d.ts +1 -28
  70. package/types/acorex-cdk-horizontal-scroll.d.ts +3 -0
  71. package/types/acorex-cdk-outline.d.ts +20 -0
  72. package/types/acorex-cdk-overlay.d.ts +60 -4
  73. package/types/acorex-cdk-resizable.d.ts +80 -38
  74. package/types/acorex-cdk-shimmer.d.ts +68 -0
  75. package/types/acorex-cdk-uploader.d.ts +1 -1
  76. package/types/acorex-cdk-viewport-guard.d.ts +99 -0
  77. package/types/acorex-cdk-wysiwyg.d.ts +118 -14
  78. package/wysiwyg/README.md +3 -1
  79. package/fesm2022/acorex-cdk-double-click.mjs +0 -178
  80. package/fesm2022/acorex-cdk-double-click.mjs.map +0 -1
  81. package/types/acorex-cdk-double-click.d.ts +0 -66
@@ -12,39 +12,45 @@ class AXResizableDirective {
12
12
  this.zone = inject(NgZone);
13
13
  this.document = inject(DOCUMENT);
14
14
  this.platformID = inject(PLATFORM_ID);
15
+ this.resizeHandles = new Map();
15
16
  this.isResizing = signal(false, /* @ts-ignore */
16
17
  ...(ngDevMode ? [{ debugName: "isResizing" }] : /* istanbul ignore next */ []));
18
+ this.activeHandle = null;
17
19
  this.initialElementWidth = 0;
18
- this.startMoveWidth = 0;
20
+ this.initialElementHeight = 0;
21
+ this.startX = 0;
22
+ this.startY = 0;
23
+ this.startWidth = 0;
24
+ this.startHeight = 0;
25
+ this.startRatio = 1;
19
26
  this.subscriptions = new Subscription();
20
- // Bound event handlers to maintain reference for cleanup
21
- this.boundMouseDown = this.onMouseDown.bind(this);
22
- this.boundMouseMove = this.onMouseMove.bind(this);
23
- this.boundMouseUp = this.onMouseUp.bind(this);
24
- this.boundMouseEnter = this.onMouseEnter.bind(this);
25
- this.boundMouseLeave = this.onMouseLeave.bind(this);
27
+ this.boundPointerDown = this.onPointerDown.bind(this);
28
+ this.boundPointerMove = this.onPointerMove.bind(this);
29
+ this.boundPointerUp = this.onPointerUp.bind(this);
30
+ this.boundPointerEnter = this.onPointerEnter.bind(this);
31
+ this.boundPointerLeave = this.onPointerLeave.bind(this);
26
32
  this.boundDoubleClick = this.onDoubleClick.bind(this);
27
- this.resizeObserver = new ResizeObserver((entries) => {
28
- const parentElement = this.hostElement.parentElement;
29
- if (!parentElement)
30
- return;
31
- for (const entry of entries) {
32
- if (entry.target === parentElement && this.maxWidth() === Infinity) {
33
- this.maxWidth.set(entry.contentRect.width);
34
- break;
35
- }
36
- }
37
- });
33
+ this.isRTL = signal(false, /* @ts-ignore */
34
+ ...(ngDevMode ? [{ debugName: "isRTL" }] : /* istanbul ignore next */ []));
38
35
  /** Define if directive is active or not */
39
36
  this.axResizable = model(true, /* @ts-ignore */
40
37
  ...(ngDevMode ? [{ debugName: "axResizable" }] : /* istanbul ignore next */ []));
38
+ /** Logical handles to render. Defaults to the inline-end edge. */
39
+ this.handles = model(['end'], /* @ts-ignore */
40
+ ...(ngDevMode ? [{ debugName: "handles" }] : /* istanbul ignore next */ []));
41
41
  /** Minimum width for the resizable element. */
42
42
  this.minWidth = model(100, /* @ts-ignore */
43
43
  ...(ngDevMode ? [{ debugName: "minWidth" }] : /* istanbul ignore next */ []));
44
44
  /** Maximum width for the resizable element. Defaults to parent width if not provided. */
45
45
  this.maxWidth = model(Infinity, /* @ts-ignore */
46
46
  ...(ngDevMode ? [{ debugName: "maxWidth" }] : /* istanbul ignore next */ []));
47
- /** Behavior on double-click: 'reset' or 'maximize'. */
47
+ /** Minimum height for the resizable element. */
48
+ this.minHeight = model(100, /* @ts-ignore */
49
+ ...(ngDevMode ? [{ debugName: "minHeight" }] : /* istanbul ignore next */ []));
50
+ /** Maximum height for the resizable element. Defaults to parent height if not provided. */
51
+ this.maxHeight = model(Infinity, /* @ts-ignore */
52
+ ...(ngDevMode ? [{ debugName: "maxHeight" }] : /* istanbul ignore next */ []));
53
+ /** Behavior on double-click: 'reset', 'maximize', or 'fit'. */
48
54
  this.dblClickAction = model('reset', /* @ts-ignore */
49
55
  ...(ngDevMode ? [{ debugName: "dblClickAction" }] : /* istanbul ignore next */ []));
50
56
  /** Define initial width for the element. */
@@ -53,281 +59,558 @@ class AXResizableDirective {
53
59
  /** Define reset width for the element. */
54
60
  this.defaultWidth = model(null, /* @ts-ignore */
55
61
  ...(ngDevMode ? [{ debugName: "defaultWidth" }] : /* istanbul ignore next */ []));
62
+ /** Define initial height for the element. */
63
+ this.height = model(null, /* @ts-ignore */
64
+ ...(ngDevMode ? [{ debugName: "height" }] : /* istanbul ignore next */ []));
65
+ /** Define reset height for the element. */
66
+ this.defaultHeight = model(null, /* @ts-ignore */
67
+ ...(ngDevMode ? [{ debugName: "defaultHeight" }] : /* istanbul ignore next */ []));
68
+ /** Lock the element's aspect ratio from the size captured at pointer-down. */
69
+ this.lockAspectRatio = model(false, /* @ts-ignore */
70
+ ...(ngDevMode ? [{ debugName: "lockAspectRatio" }] : /* istanbul ignore next */ []));
56
71
  /** Event emitted when resizing starts. */
57
72
  this.onResizingStarted = output();
58
73
  /** Event emitted when resizing ends. */
59
74
  this.onResizingEnded = output();
60
75
  /** Event emitted on double-click. */
61
76
  this.onResizingDblClick = output();
62
- this.isRTL = signal(AXHtmlUtil.isRtl(this.document.documentElement), /* @ts-ignore */
63
- ...(ngDevMode ? [{ debugName: "isRTL" }] : /* istanbul ignore next */ []));
64
77
  this.isBrowser = isPlatformBrowser(this.platformID);
65
78
  this.hostElement = this.el.nativeElement;
79
+ this.isRTL.set(AXHtmlUtil.isRtl(this.document.documentElement));
66
80
  this.subscriptions.add(this.platformService.directionChange.subscribe((i) => {
67
81
  this.isRTL.set(i.data === 'rtl');
68
- if (this.resizeHandle) {
69
- this.updateHandlePosition();
70
- }
71
82
  }));
72
- if (this.isBrowser) {
73
- effect(() => {
74
- if (this.isResizing()) {
75
- return;
83
+ if (!this.isBrowser) {
84
+ return;
85
+ }
86
+ this.resizeObserver = new ResizeObserver((entries) => {
87
+ const parentElement = this.hostElement.parentElement;
88
+ if (!parentElement) {
89
+ return;
90
+ }
91
+ for (const entry of entries) {
92
+ if (entry.target !== parentElement) {
93
+ continue;
94
+ }
95
+ if (this.maxWidth() === Infinity) {
96
+ this.maxWidth.set(entry.contentRect.width);
76
97
  }
77
- const resolvedWidth = this.width() ?? this.defaultWidth();
78
- if (resolvedWidth !== null) {
79
- this.applyElementWidth(resolvedWidth);
98
+ if (this.maxHeight() === Infinity) {
99
+ this.maxHeight.set(entry.contentRect.height);
80
100
  }
81
- });
82
- }
101
+ }
102
+ });
103
+ effect(() => {
104
+ const isActive = this.axResizable();
105
+ const handles = this.handles();
106
+ this.reconcileHandles(isActive, handles);
107
+ });
108
+ effect(() => {
109
+ this.isRTL();
110
+ this.updateAllHandlePositions();
111
+ });
112
+ effect(() => {
113
+ if (this.isResizing()) {
114
+ return;
115
+ }
116
+ this.applySizeFromModel();
117
+ });
83
118
  }
84
119
  ngAfterViewInit() {
85
- if (!this.isBrowser)
120
+ if (!this.isBrowser) {
86
121
  return;
122
+ }
87
123
  this.initialElementWidth = this.hostElement.offsetWidth;
88
- this.applyWidthFromModel();
124
+ this.initialElementHeight = this.hostElement.offsetHeight;
125
+ this.applySizeFromModel();
126
+ const parentElement = this.hostElement.parentElement;
89
127
  if (this.maxWidth() === Infinity) {
90
- const parentWidth = this.hostElement.parentElement?.offsetWidth;
128
+ const parentWidth = parentElement?.offsetWidth;
91
129
  if (parentWidth) {
92
130
  this.maxWidth.set(parentWidth);
93
131
  }
94
132
  }
95
- const parentElement = this.hostElement.parentElement;
133
+ if (this.maxHeight() === Infinity) {
134
+ const parentHeight = parentElement?.offsetHeight;
135
+ if (parentHeight) {
136
+ this.maxHeight.set(parentHeight);
137
+ }
138
+ }
96
139
  if (parentElement) {
97
- this.resizeObserver.observe(parentElement);
140
+ this.resizeObserver?.observe(parentElement);
98
141
  }
99
- this.createResizeHandle();
100
- this.setupResizableState();
101
142
  }
102
143
  ngOnDestroy() {
103
144
  this.subscriptions.unsubscribe();
104
- this.resizeObserver.disconnect();
105
- this.cleanupEventListeners();
106
- }
107
- setupResizableState() {
108
- this.subscriptions.add(this.axResizable.subscribe((isActive) => {
109
- if (!isActive) {
110
- this.applyWidthFromModel();
111
- this.cleanupEventListeners();
112
- }
113
- else {
114
- this.applyWidthFromModel();
115
- this.createResizeHandle();
116
- }
117
- }));
145
+ this.resizeObserver?.disconnect();
146
+ this.destroyAllHandles();
147
+ this.document.body.style.cursor = '';
118
148
  }
119
- applyWidthFromModel() {
120
- const width = this.width();
121
- if (width !== null) {
122
- this.applyElementWidth(width);
149
+ reconcileHandles(isActive, handles) {
150
+ if (!this.isBrowser) {
151
+ return;
152
+ }
153
+ if (!isActive) {
154
+ this.stopResizing();
155
+ this.destroyAllHandles();
156
+ this.applySizeFromModel();
123
157
  return;
124
158
  }
125
- const defaultWidth = this.defaultWidth();
126
- if (defaultWidth !== null) {
127
- this.applyElementWidth(defaultWidth);
159
+ this.hostElement.style.position = 'relative';
160
+ const unique = [...new Set(handles)];
161
+ const desired = new Set(unique);
162
+ for (const [type, element] of this.resizeHandles) {
163
+ if (!desired.has(type)) {
164
+ this.destroyHandle(type, element);
165
+ }
166
+ }
167
+ for (const type of unique) {
168
+ if (!this.resizeHandles.has(type)) {
169
+ this.createHandle(type);
170
+ }
128
171
  }
129
172
  }
130
- applyElementWidth(width) {
131
- this.hostElement.style.width = `${width}px`;
173
+ createHandle(type) {
174
+ const handle = this.document.createElement('div');
175
+ handle.classList.add('ax-resizable-handler', `ax-resizable-handler--${type}`);
176
+ handle.dataset['axResizeHandle'] = type;
177
+ this.hostElement.appendChild(handle);
178
+ this.applyHandleStyles(handle, type);
179
+ this.attachHandleListeners(handle);
180
+ this.resizeHandles.set(type, handle);
132
181
  }
133
- createResizeHandle() {
134
- if (!this.axResizable() || this.resizeHandle)
135
- return;
136
- this.hostElement.style.position = 'relative';
137
- this.resizeHandle = this.document.createElement('div');
138
- this.resizeHandle.classList.add('ax-resizable-handler');
139
- this.hostElement.appendChild(this.resizeHandle);
140
- this.applyHandleStyles();
141
- this.attachEventListeners();
142
- }
143
- applyHandleStyles() {
144
- if (!this.resizeHandle)
145
- return;
146
- Object.assign(this.resizeHandle.style, {
147
- width: STYLES.handlerWidth,
148
- backgroundColor: STYLES.backgroundColor,
182
+ attachHandleListeners(handle) {
183
+ this.zone.runOutsideAngular(() => {
184
+ handle.addEventListener('pointerdown', this.boundPointerDown);
185
+ handle.addEventListener('pointermove', this.boundPointerMove);
186
+ handle.addEventListener('pointerup', this.boundPointerUp);
187
+ handle.addEventListener('pointercancel', this.boundPointerUp);
188
+ handle.addEventListener('pointerenter', this.boundPointerEnter);
189
+ handle.addEventListener('pointerleave', this.boundPointerLeave);
190
+ handle.addEventListener('dblclick', this.boundDoubleClick);
191
+ });
192
+ }
193
+ destroyHandle(type, handle) {
194
+ handle.removeEventListener('pointerdown', this.boundPointerDown);
195
+ handle.removeEventListener('pointermove', this.boundPointerMove);
196
+ handle.removeEventListener('pointerup', this.boundPointerUp);
197
+ handle.removeEventListener('pointercancel', this.boundPointerUp);
198
+ handle.removeEventListener('pointerenter', this.boundPointerEnter);
199
+ handle.removeEventListener('pointerleave', this.boundPointerLeave);
200
+ handle.removeEventListener('dblclick', this.boundDoubleClick);
201
+ handle.remove();
202
+ this.resizeHandles.delete(type);
203
+ }
204
+ destroyAllHandles() {
205
+ for (const [type, handle] of [...this.resizeHandles]) {
206
+ this.destroyHandle(type, handle);
207
+ }
208
+ }
209
+ applyHandleStyles(handle, type) {
210
+ const isCorner = type.includes('-');
211
+ Object.assign(handle.style, {
149
212
  position: 'absolute',
150
- top: '0',
151
- bottom: '0',
152
- cursor: STYLES.cursor,
153
- zIndex: STYLES.zIndex,
213
+ backgroundColor: STYLES.backgroundColor,
214
+ zIndex: isCorner ? STYLES.zIndexCorner : STYLES.zIndex,
154
215
  transition: STYLES.transition,
155
216
  borderRadius: STYLES.borderRadius,
156
217
  userSelect: 'none',
218
+ touchAction: 'none',
219
+ cursor: this.getCursorForHandle(type),
220
+ left: '',
221
+ right: '',
222
+ top: '',
223
+ bottom: '',
224
+ width: '',
225
+ height: '',
157
226
  });
158
- this.updateHandlePosition();
227
+ this.positionHandle(handle, type);
159
228
  }
160
- updateHandlePosition() {
161
- if (!this.resizeHandle)
162
- return;
163
- const isRTL = this.isRTL();
164
- if (isRTL) {
165
- this.resizeHandle.style.left = '0';
166
- this.resizeHandle.style.right = '';
229
+ updateAllHandlePositions() {
230
+ for (const [type, handle] of this.resizeHandles) {
231
+ handle.style.cursor = this.getCursorForHandle(type);
232
+ this.positionHandle(handle, type);
233
+ }
234
+ }
235
+ positionHandle(handle, type) {
236
+ const rtl = this.isRTL();
237
+ switch (type) {
238
+ case 'start':
239
+ case 'end':
240
+ handle.style.top = '0';
241
+ handle.style.bottom = '0';
242
+ handle.style.width = STYLES.handlerWidth;
243
+ this.applyInlineSide(handle, type, rtl);
244
+ break;
245
+ case 'top':
246
+ case 'bottom':
247
+ handle.style.left = '0';
248
+ handle.style.right = '0';
249
+ handle.style.height = STYLES.handlerHeight;
250
+ if (type === 'top') {
251
+ handle.style.top = '0';
252
+ handle.style.bottom = '';
253
+ }
254
+ else {
255
+ handle.style.bottom = '0';
256
+ handle.style.top = '';
257
+ }
258
+ break;
259
+ default: {
260
+ const [vertical, horizontal] = type.split('-');
261
+ handle.style.width = STYLES.cornerSize;
262
+ handle.style.height = STYLES.cornerSize;
263
+ if (vertical === 'top') {
264
+ handle.style.top = '0';
265
+ handle.style.bottom = '';
266
+ }
267
+ else {
268
+ handle.style.bottom = '0';
269
+ handle.style.top = '';
270
+ }
271
+ this.applyInlineSide(handle, horizontal, rtl);
272
+ break;
273
+ }
274
+ }
275
+ }
276
+ applyInlineSide(element, side, rtl) {
277
+ const physicalLeft = (side === 'start' && !rtl) || (side === 'end' && rtl);
278
+ if (physicalLeft) {
279
+ element.style.left = '0';
280
+ element.style.right = '';
167
281
  }
168
282
  else {
169
- this.resizeHandle.style.right = '0';
170
- this.resizeHandle.style.left = '';
283
+ element.style.right = '0';
284
+ element.style.left = '';
171
285
  }
172
286
  }
173
- attachEventListeners() {
174
- if (!this.resizeHandle)
175
- return;
176
- const handle = this.resizeHandle;
177
- this.zone.runOutsideAngular(() => {
178
- handle.addEventListener('mousedown', this.boundMouseDown);
179
- handle.addEventListener('mouseenter', this.boundMouseEnter);
180
- handle.addEventListener('mouseleave', this.boundMouseLeave);
181
- handle.addEventListener('dblclick', this.boundDoubleClick);
182
- this.document.addEventListener('mousemove', this.boundMouseMove);
183
- this.document.addEventListener('mouseup', this.boundMouseUp);
184
- });
287
+ applySizeFromModel() {
288
+ const width = this.width() ?? this.defaultWidth();
289
+ const height = this.height() ?? this.defaultHeight();
290
+ this.applySize(width, height);
185
291
  }
186
- cleanupEventListeners() {
187
- if (this.resizeHandle) {
188
- this.resizeHandle.removeEventListener('mousedown', this.boundMouseDown);
189
- this.resizeHandle.removeEventListener('mouseenter', this.boundMouseEnter);
190
- this.resizeHandle.removeEventListener('mouseleave', this.boundMouseLeave);
191
- this.resizeHandle.removeEventListener('dblclick', this.boundDoubleClick);
192
- this.resizeHandle.remove();
193
- this.resizeHandle = undefined;
194
- }
195
- this.document.removeEventListener('mousemove', this.boundMouseMove);
196
- this.document.removeEventListener('mouseup', this.boundMouseUp);
197
- this.document.body.style.cursor = '';
292
+ applySize(width, height) {
293
+ if (width !== null) {
294
+ this.hostElement.style.width = `${width}px`;
295
+ }
296
+ if (height !== null) {
297
+ this.hostElement.style.height = `${height}px`;
298
+ }
198
299
  }
199
- onMouseDown(event) {
200
- if (!this.resizeHandle)
201
- return;
202
- const handleRect = this.resizeHandle.getBoundingClientRect();
203
- if (event.clientX < handleRect.left || event.clientX > handleRect.right)
300
+ onPointerDown(event) {
301
+ const handleType = this.getHandleType(event);
302
+ const handle = event.currentTarget;
303
+ if (!handleType || !handle) {
204
304
  return;
305
+ }
205
306
  event.preventDefault();
307
+ event.stopPropagation();
308
+ try {
309
+ handle.setPointerCapture?.(event.pointerId);
310
+ }
311
+ catch {
312
+ // Pointer capture can throw for synthetic or inactive pointers.
313
+ }
314
+ this.activeHandle = handleType;
206
315
  this.isResizing.set(true);
207
- this.document.body.style.cursor = STYLES.cursorActive;
208
- this.resizeHandle.style.backgroundColor = STYLES.backgroundColorActive;
209
- this.startMoveWidth = this.hostElement.offsetWidth;
316
+ this.startX = event.clientX;
317
+ this.startY = event.clientY;
318
+ this.startWidth = this.hostElement.offsetWidth;
319
+ this.startHeight = this.hostElement.offsetHeight;
320
+ this.startRatio = this.startHeight > 0 ? this.startWidth / this.startHeight : 1;
321
+ this.document.body.style.cursor = this.getActiveCursor(handleType);
322
+ handle.style.backgroundColor = STYLES.backgroundColorActive;
323
+ const size = { width: this.startWidth, height: this.startHeight };
210
324
  this.zone.run(() => {
211
- this.onResizingStarted.emit({
212
- component: this,
213
- htmlElement: this.hostElement,
214
- isUserInteraction: true,
215
- name: 'resizingStarted',
216
- value: this.startMoveWidth,
217
- oldValue: this.startMoveWidth,
218
- });
325
+ this.onResizingStarted.emit(this.createResizeEvent('resizingStarted', size, size));
219
326
  });
220
327
  }
221
- onMouseMove(event) {
222
- if (!this.isResizing())
328
+ onPointerMove(event) {
329
+ if (!this.isResizing() || !this.activeHandle) {
223
330
  return;
224
- const rect = this.hostElement.getBoundingClientRect();
225
- const isRTL = this.isRTL();
226
- let newWidth = isRTL ? rect.right - event.clientX : event.clientX - rect.left;
227
- newWidth = Math.max(this.minWidth(), Math.min(newWidth, this.maxWidth()));
228
- if (newWidth !== this.hostElement.offsetWidth) {
229
- this.hostElement.style.width = `${newWidth}px`;
230
331
  }
332
+ const axes = getHandleAxes(this.activeHandle);
333
+ const lock = this.lockAspectRatio();
334
+ const next = this.computeSize(event, this.activeHandle);
335
+ event.preventDefault();
336
+ this.applySize(axes.horizontal || lock ? next.width : null, axes.vertical || lock ? next.height : null);
231
337
  }
232
- onMouseUp() {
233
- if (!this.isResizing() || !this.resizeHandle)
338
+ onPointerUp(event) {
339
+ if (!this.isResizing()) {
234
340
  return;
341
+ }
342
+ const handle = event.currentTarget;
343
+ try {
344
+ handle?.releasePointerCapture?.(event.pointerId);
345
+ }
346
+ catch {
347
+ // Pointer capture may already have been released.
348
+ }
349
+ const axes = this.activeHandle ? getHandleAxes(this.activeHandle) : null;
350
+ const current = this.getCurrentSize();
351
+ const oldSize = { width: this.startWidth, height: this.startHeight };
235
352
  this.document.body.style.cursor = '';
236
- this.resizeHandle.style.backgroundColor = STYLES.backgroundColor;
237
- const currentWidth = this.hostElement.offsetWidth;
353
+ if (handle) {
354
+ handle.style.backgroundColor = STYLES.backgroundColor;
355
+ }
238
356
  this.zone.run(() => {
239
- this.width.set(currentWidth);
240
- this.onResizingEnded.emit({
241
- component: this,
242
- htmlElement: this.hostElement,
243
- isUserInteraction: true,
244
- name: 'resizingEnded',
245
- value: currentWidth,
246
- oldValue: this.startMoveWidth,
247
- });
357
+ if (axes?.horizontal) {
358
+ this.width.set(current.width);
359
+ }
360
+ if (axes?.vertical) {
361
+ this.height.set(current.height);
362
+ }
363
+ this.onResizingEnded.emit(this.createResizeEvent('resizingEnded', current, oldSize));
248
364
  });
249
- this.isResizing.set(false);
365
+ this.stopResizing();
250
366
  }
251
- onMouseEnter() {
252
- if (!this.isResizing() && this.resizeHandle) {
253
- this.resizeHandle.style.backgroundColor = STYLES.backgroundColorHover;
367
+ onPointerEnter(event) {
368
+ if (this.isResizing()) {
369
+ return;
370
+ }
371
+ const handle = event.currentTarget;
372
+ if (handle) {
373
+ handle.style.backgroundColor = STYLES.backgroundColorHover;
254
374
  }
255
375
  }
256
- onMouseLeave() {
257
- if (!this.isResizing() && this.resizeHandle) {
258
- this.resizeHandle.style.backgroundColor = STYLES.backgroundColor;
376
+ onPointerLeave(event) {
377
+ if (this.isResizing()) {
378
+ return;
379
+ }
380
+ const handle = event.currentTarget;
381
+ if (handle) {
382
+ handle.style.backgroundColor = STYLES.backgroundColor;
259
383
  }
260
384
  }
261
- onDoubleClick() {
262
- const elementWidth = this.hostElement.offsetWidth;
385
+ onDoubleClick(event) {
386
+ const handleType = this.getHandleType(event);
387
+ if (!handleType) {
388
+ return;
389
+ }
390
+ event.preventDefault();
391
+ const axes = getHandleAxes(handleType);
392
+ const oldSize = this.getCurrentSize();
263
393
  const action = this.dblClickAction();
264
- let newWidth;
394
+ let size;
265
395
  switch (action) {
266
396
  case 'reset':
267
- newWidth = this.resetToInitialWidth();
397
+ size = this.resetToInitialSize(axes);
268
398
  break;
269
399
  case 'maximize':
270
- newWidth = this.maximizeToMaxWidth();
400
+ size = this.maximizeToMaxSize(axes);
271
401
  break;
272
402
  case 'fit':
273
- newWidth = this.fitToContent();
403
+ size = this.fitToContent(axes);
274
404
  break;
275
405
  default:
276
- newWidth = elementWidth;
406
+ size = oldSize;
277
407
  }
278
408
  this.zone.run(() => {
279
- this.onResizingDblClick.emit({
280
- component: this,
281
- htmlElement: this.hostElement,
282
- isUserInteraction: true,
283
- name: 'onResizingDblClick',
284
- oldValue: elementWidth,
285
- value: newWidth,
286
- });
409
+ this.onResizingDblClick.emit(this.createResizeEvent('onResizingDblClick', size, oldSize));
287
410
  });
288
411
  }
289
- resetToInitialWidth() {
290
- const defaultWidth = this.defaultWidth();
291
- if (defaultWidth !== null) {
292
- this.applyElementWidth(defaultWidth);
293
- return defaultWidth;
412
+ computeSize(event, handle) {
413
+ const dx = event.clientX - this.startX;
414
+ const dy = event.clientY - this.startY;
415
+ const rtl = this.isRTL();
416
+ const axes = getHandleAxes(handle);
417
+ const lock = this.lockAspectRatio();
418
+ let width = this.startWidth;
419
+ let height = this.startHeight;
420
+ if (axes.horizontal === 'end') {
421
+ width = this.startWidth + (rtl ? -dx : dx);
422
+ }
423
+ else if (axes.horizontal === 'start') {
424
+ width = this.startWidth + (rtl ? dx : -dx);
425
+ }
426
+ if (axes.vertical === 'bottom') {
427
+ height = this.startHeight + dy;
428
+ }
429
+ else if (axes.vertical === 'top') {
430
+ height = this.startHeight - dy;
431
+ }
432
+ if (lock) {
433
+ const ratio = this.startRatio > 0 ? this.startRatio : 1;
434
+ if (axes.horizontal && axes.vertical) {
435
+ const widthDelta = Math.abs(width - this.startWidth);
436
+ const heightDelta = Math.abs(height - this.startHeight);
437
+ if (widthDelta >= heightDelta) {
438
+ height = width / ratio;
439
+ }
440
+ else {
441
+ width = height * ratio;
442
+ }
443
+ }
444
+ else if (axes.horizontal) {
445
+ height = width / ratio;
446
+ }
447
+ else if (axes.vertical) {
448
+ width = height * ratio;
449
+ }
450
+ }
451
+ return this.clampSize(width, height, lock);
452
+ }
453
+ clampSize(width, height, lock) {
454
+ const minW = this.minWidth();
455
+ const maxW = this.maxWidth();
456
+ const minH = this.minHeight();
457
+ const maxH = this.maxHeight();
458
+ if (!lock) {
459
+ return {
460
+ width: Math.max(minW, Math.min(width, maxW)),
461
+ height: Math.max(minH, Math.min(height, maxH)),
462
+ };
463
+ }
464
+ const ratio = this.startRatio > 0 ? this.startRatio : 1;
465
+ width = Math.max(minW, width);
466
+ height = width / ratio;
467
+ if (height < minH) {
468
+ height = minH;
469
+ width = height * ratio;
470
+ }
471
+ if (width > maxW) {
472
+ width = maxW;
473
+ height = width / ratio;
474
+ }
475
+ if (height > maxH) {
476
+ height = maxH;
477
+ width = height * ratio;
478
+ }
479
+ if (width < minW) {
480
+ width = minW;
481
+ height = width / ratio;
482
+ }
483
+ if (height < minH) {
484
+ height = minH;
485
+ width = height * ratio;
486
+ }
487
+ return {
488
+ width: Math.max(minW, Math.min(width, maxW)),
489
+ height: Math.max(minH, Math.min(height, maxH)),
490
+ };
491
+ }
492
+ resetToInitialSize(axes) {
493
+ const size = this.getCurrentSize();
494
+ if (axes.horizontal) {
495
+ const next = this.defaultWidth() ?? this.width() ?? this.initialElementWidth;
496
+ this.applySize(next, null);
497
+ size.width = next;
498
+ }
499
+ if (axes.vertical) {
500
+ const next = this.defaultHeight() ?? this.height() ?? this.initialElementHeight;
501
+ this.applySize(null, next);
502
+ size.height = next;
503
+ }
504
+ return size;
505
+ }
506
+ maximizeToMaxSize(axes) {
507
+ const size = this.getCurrentSize();
508
+ if (axes.horizontal && this.maxWidth() !== Infinity) {
509
+ this.applySize(this.maxWidth(), null);
510
+ size.width = this.maxWidth();
511
+ }
512
+ if (axes.vertical && this.maxHeight() !== Infinity) {
513
+ this.applySize(null, this.maxHeight());
514
+ size.height = this.maxHeight();
515
+ }
516
+ return size;
517
+ }
518
+ fitToContent(axes) {
519
+ if (axes.horizontal) {
520
+ this.hostElement.style.width = 'fit-content';
521
+ }
522
+ if (axes.vertical) {
523
+ this.hostElement.style.height = 'fit-content';
524
+ }
525
+ return this.getCurrentSize();
526
+ }
527
+ getCurrentSize() {
528
+ return {
529
+ width: this.hostElement.offsetWidth,
530
+ height: this.hostElement.offsetHeight,
531
+ };
532
+ }
533
+ createResizeEvent(name, size, oldSize) {
534
+ return {
535
+ component: this,
536
+ htmlElement: this.hostElement,
537
+ isUserInteraction: true,
538
+ name,
539
+ value: size.width,
540
+ oldValue: oldSize.width,
541
+ size,
542
+ oldSize,
543
+ };
544
+ }
545
+ getHandleType(event) {
546
+ const target = event.currentTarget;
547
+ const value = target?.dataset['axResizeHandle'];
548
+ return value ?? null;
549
+ }
550
+ getCursorForHandle(type) {
551
+ if (type === 'start' || type === 'end') {
552
+ return STYLES.cursorHorizontal;
294
553
  }
295
- const initialWidth = this.width();
296
- if (initialWidth !== null) {
297
- this.applyElementWidth(initialWidth);
298
- return initialWidth;
554
+ if (type === 'top' || type === 'bottom') {
555
+ return STYLES.cursorVertical;
299
556
  }
300
- this.applyElementWidth(this.initialElementWidth);
301
- return this.initialElementWidth;
557
+ const nwseInLtr = type === 'bottom-end' || type === 'top-start';
558
+ const useNwse = this.isRTL() ? !nwseInLtr : nwseInLtr;
559
+ return useNwse ? STYLES.cursorCorner : STYLES.cursorCornerAlt;
302
560
  }
303
- maximizeToMaxWidth() {
304
- const maxWidth = this.maxWidth();
305
- if (maxWidth !== Infinity) {
306
- this.applyElementWidth(maxWidth);
561
+ getActiveCursor(type) {
562
+ if (type === 'start' || type === 'end') {
563
+ return STYLES.cursorActive;
307
564
  }
308
- return maxWidth;
565
+ return this.getCursorForHandle(type);
309
566
  }
310
- fitToContent() {
311
- this.hostElement.style.width = 'fit-content';
312
- return this.hostElement.clientWidth;
567
+ stopResizing() {
568
+ this.activeHandle = null;
569
+ this.isResizing.set(false);
313
570
  }
314
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXResizableDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
315
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.8", type: AXResizableDirective, isStandalone: true, selector: "[axResizable]", inputs: { axResizable: { classPropertyName: "axResizable", publicName: "axResizable", isSignal: true, isRequired: false, transformFunction: null }, minWidth: { classPropertyName: "minWidth", publicName: "minWidth", isSignal: true, isRequired: false, transformFunction: null }, maxWidth: { classPropertyName: "maxWidth", publicName: "maxWidth", isSignal: true, isRequired: false, transformFunction: null }, dblClickAction: { classPropertyName: "dblClickAction", publicName: "dblClickAction", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, defaultWidth: { classPropertyName: "defaultWidth", publicName: "defaultWidth", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { axResizable: "axResizableChange", minWidth: "minWidthChange", maxWidth: "maxWidthChange", dblClickAction: "dblClickActionChange", width: "widthChange", defaultWidth: "defaultWidthChange", onResizingStarted: "onResizingStarted", onResizingEnded: "onResizingEnded", onResizingDblClick: "onResizingDblClick" }, ngImport: i0 }); }
571
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: AXResizableDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
572
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.6", type: AXResizableDirective, isStandalone: true, selector: "[axResizable]", inputs: { axResizable: { classPropertyName: "axResizable", publicName: "axResizable", isSignal: true, isRequired: false, transformFunction: null }, handles: { classPropertyName: "handles", publicName: "handles", isSignal: true, isRequired: false, transformFunction: null }, minWidth: { classPropertyName: "minWidth", publicName: "minWidth", isSignal: true, isRequired: false, transformFunction: null }, maxWidth: { classPropertyName: "maxWidth", publicName: "maxWidth", isSignal: true, isRequired: false, transformFunction: null }, minHeight: { classPropertyName: "minHeight", publicName: "minHeight", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "maxHeight", isSignal: true, isRequired: false, transformFunction: null }, dblClickAction: { classPropertyName: "dblClickAction", publicName: "dblClickAction", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, defaultWidth: { classPropertyName: "defaultWidth", publicName: "defaultWidth", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, defaultHeight: { classPropertyName: "defaultHeight", publicName: "defaultHeight", isSignal: true, isRequired: false, transformFunction: null }, lockAspectRatio: { classPropertyName: "lockAspectRatio", publicName: "lockAspectRatio", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { axResizable: "axResizableChange", handles: "handlesChange", minWidth: "minWidthChange", maxWidth: "maxWidthChange", minHeight: "minHeightChange", maxHeight: "maxHeightChange", dblClickAction: "dblClickActionChange", width: "widthChange", defaultWidth: "defaultWidthChange", height: "heightChange", defaultHeight: "defaultHeightChange", lockAspectRatio: "lockAspectRatioChange", onResizingStarted: "onResizingStarted", onResizingEnded: "onResizingEnded", onResizingDblClick: "onResizingDblClick" }, ngImport: i0 }); }
316
573
  }
317
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXResizableDirective, decorators: [{
574
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: AXResizableDirective, decorators: [{
318
575
  type: Directive,
319
576
  args: [{
320
577
  selector: '[axResizable]',
321
578
  }]
322
- }], ctorParameters: () => [], propDecorators: { axResizable: [{ type: i0.Input, args: [{ isSignal: true, alias: "axResizable", required: false }] }, { type: i0.Output, args: ["axResizableChange"] }], minWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "minWidth", required: false }] }, { type: i0.Output, args: ["minWidthChange"] }], maxWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxWidth", required: false }] }, { type: i0.Output, args: ["maxWidthChange"] }], dblClickAction: [{ type: i0.Input, args: [{ isSignal: true, alias: "dblClickAction", required: false }] }, { type: i0.Output, args: ["dblClickActionChange"] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }, { type: i0.Output, args: ["widthChange"] }], defaultWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultWidth", required: false }] }, { type: i0.Output, args: ["defaultWidthChange"] }], onResizingStarted: [{ type: i0.Output, args: ["onResizingStarted"] }], onResizingEnded: [{ type: i0.Output, args: ["onResizingEnded"] }], onResizingDblClick: [{ type: i0.Output, args: ["onResizingDblClick"] }] } });
579
+ }], ctorParameters: () => [], propDecorators: { axResizable: [{ type: i0.Input, args: [{ isSignal: true, alias: "axResizable", required: false }] }, { type: i0.Output, args: ["axResizableChange"] }], handles: [{ type: i0.Input, args: [{ isSignal: true, alias: "handles", required: false }] }, { type: i0.Output, args: ["handlesChange"] }], minWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "minWidth", required: false }] }, { type: i0.Output, args: ["minWidthChange"] }], maxWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxWidth", required: false }] }, { type: i0.Output, args: ["maxWidthChange"] }], minHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "minHeight", required: false }] }, { type: i0.Output, args: ["minHeightChange"] }], maxHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxHeight", required: false }] }, { type: i0.Output, args: ["maxHeightChange"] }], dblClickAction: [{ type: i0.Input, args: [{ isSignal: true, alias: "dblClickAction", required: false }] }, { type: i0.Output, args: ["dblClickActionChange"] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }, { type: i0.Output, args: ["widthChange"] }], defaultWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultWidth", required: false }] }, { type: i0.Output, args: ["defaultWidthChange"] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }, { type: i0.Output, args: ["heightChange"] }], defaultHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultHeight", required: false }] }, { type: i0.Output, args: ["defaultHeightChange"] }], lockAspectRatio: [{ type: i0.Input, args: [{ isSignal: true, alias: "lockAspectRatio", required: false }] }, { type: i0.Output, args: ["lockAspectRatioChange"] }], onResizingStarted: [{ type: i0.Output, args: ["onResizingStarted"] }], onResizingEnded: [{ type: i0.Output, args: ["onResizingEnded"] }], onResizingDblClick: [{ type: i0.Output, args: ["onResizingDblClick"] }] } });
580
+ function getHandleAxes(handle) {
581
+ switch (handle) {
582
+ case 'start':
583
+ return { horizontal: 'start', vertical: null };
584
+ case 'end':
585
+ return { horizontal: 'end', vertical: null };
586
+ case 'top':
587
+ return { horizontal: null, vertical: 'top' };
588
+ case 'bottom':
589
+ return { horizontal: null, vertical: 'bottom' };
590
+ case 'top-start':
591
+ return { horizontal: 'start', vertical: 'top' };
592
+ case 'top-end':
593
+ return { horizontal: 'end', vertical: 'top' };
594
+ case 'bottom-start':
595
+ return { horizontal: 'start', vertical: 'bottom' };
596
+ case 'bottom-end':
597
+ return { horizontal: 'end', vertical: 'bottom' };
598
+ }
599
+ }
323
600
  const STYLES = {
324
601
  handlerWidth: 'var(--ax-comp-resizable-handler-width, 4px)',
602
+ handlerHeight: 'var(--ax-comp-resizable-handler-height, 4px)',
603
+ cornerSize: 'var(--ax-comp-resizable-corner-size, 10px)',
325
604
  backgroundColor: 'rgba(var(--ax-comp-resizable-background-color))',
326
605
  backgroundColorActive: 'rgba(var(--ax-comp-resizable-background-color-active, var(--ax-sys-color-primary-surface)))',
327
606
  backgroundColorHover: 'rgba(var(--ax-comp-resizable-background-color-hover, var(--ax-sys-color-primary-light-surface)))',
328
- cursor: 'var(--ax-comp-resizable-cursor, ew-resize)',
607
+ cursorHorizontal: 'var(--ax-comp-resizable-cursor, ew-resize)',
608
+ cursorVertical: 'var(--ax-comp-resizable-cursor-vertical, ns-resize)',
609
+ cursorCorner: 'var(--ax-comp-resizable-cursor-corner, nwse-resize)',
610
+ cursorCornerAlt: 'var(--ax-comp-resizable-cursor-corner-alt, nesw-resize)',
329
611
  cursorActive: 'var(--ax-comp-resizable-cursor-active, ew-resize)',
330
612
  zIndex: 'var(--ax-comp-resizable-z-index, 999)',
613
+ zIndexCorner: 'var(--ax-comp-resizable-z-index-corner, 1000)',
331
614
  transition: 'var(--ax-comp-resizable-transition, background-color --ax-sys-transition-duration --ax-sys-transition-timing-function)',
332
615
  borderRadius: 'var(--ax-comp-resizable-border-radius, --ax-sys-border-radius)',
333
616
  };