igniteui-angular 22.1.0-beta.0 → 22.1.0-beta.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 (40) hide show
  1. package/fesm2022/igniteui-angular-carousel.mjs +2 -2
  2. package/fesm2022/igniteui-angular-carousel.mjs.map +1 -1
  3. package/fesm2022/igniteui-angular-core.mjs +83 -24
  4. package/fesm2022/igniteui-angular-core.mjs.map +1 -1
  5. package/fesm2022/igniteui-angular-grids-grid.mjs +9 -0
  6. package/fesm2022/igniteui-angular-grids-grid.mjs.map +1 -1
  7. package/fesm2022/igniteui-angular-list.mjs +14 -1
  8. package/fesm2022/igniteui-angular-list.mjs.map +1 -1
  9. package/fesm2022/igniteui-angular-navigation-drawer.mjs +6 -1
  10. package/fesm2022/igniteui-angular-navigation-drawer.mjs.map +1 -1
  11. package/package.json +1 -1
  12. package/skills/igniteui-angular-components/SKILL.md +9 -29
  13. package/skills/igniteui-angular-components/references/charts.md +3 -33
  14. package/skills/igniteui-angular-components/references/data-display.md +8 -94
  15. package/skills/igniteui-angular-components/references/directives.md +13 -114
  16. package/skills/igniteui-angular-components/references/feedback.md +1 -4
  17. package/skills/igniteui-angular-components/references/form-controls.md +10 -75
  18. package/skills/igniteui-angular-components/references/layout-manager.md +15 -198
  19. package/skills/igniteui-angular-components/references/layout.md +1 -4
  20. package/skills/igniteui-angular-components/references/mcp-setup.md +28 -29
  21. package/skills/igniteui-angular-components/references/setup.md +6 -4
  22. package/skills/igniteui-angular-figma-to-app/SKILL.md +37 -25
  23. package/skills/igniteui-angular-figma-to-app/references/figma-component-map.md +25 -26
  24. package/skills/igniteui-angular-figma-to-app/references/mcp-setup.md +13 -9
  25. package/skills/igniteui-angular-figma-to-app/references/validation-patterns.md +2 -2
  26. package/skills/igniteui-angular-generate-from-image-design/SKILL.md +22 -7
  27. package/skills/igniteui-angular-generate-from-image-design/references/component-mapping.md +1 -1
  28. package/skills/igniteui-angular-grids/SKILL.md +21 -25
  29. package/skills/igniteui-angular-grids/references/data-operations.md +10 -11
  30. package/skills/igniteui-angular-grids/references/editing.md +3 -4
  31. package/skills/igniteui-angular-grids/references/features.md +16 -38
  32. package/skills/igniteui-angular-grids/references/grid-migration.md +6 -8
  33. package/skills/igniteui-angular-grids/references/paging-remote.md +2 -4
  34. package/skills/igniteui-angular-grids/references/state.md +4 -5
  35. package/skills/igniteui-angular-grids/references/structure.md +16 -9
  36. package/skills/igniteui-angular-grids/references/types.md +19 -33
  37. package/skills/igniteui-angular-theming/SKILL.md +12 -65
  38. package/skills/igniteui-angular-theming/references/mcp-setup.md +28 -31
  39. package/types/igniteui-angular-core.d.ts +32 -5
  40. package/types/igniteui-angular-list.d.ts +5 -0
@@ -1021,8 +1021,10 @@ const EDITOR_PROVIDER = new InjectionToken('EditorProvider');
1021
1021
  *
1022
1022
  * Consolidates the pan/swipe/tap recognition logic shared across components
1023
1023
  * (carousel, navigation drawer, list item, time picker) on top of native
1024
- * Pointer Events. It does not depend on `NgZone`; consumers update their own
1025
- * state inside the provided callbacks.
1024
+ * Pointer Events. It does not require `NgZone`; consumers update their own
1025
+ * state inside the provided callbacks. An `NgZone` can optionally be supplied so
1026
+ * that the listeners are attached outside of Angular and only the discrete
1027
+ * callbacks re-enter it, keeping continuous dragging free of change detection.
1026
1028
  *
1027
1029
  * Outside of a browser environment (e.g. during server-side rendering) it is a
1028
1030
  * noop: no listeners are attached and no callbacks are invoked, so consumers can
@@ -1054,7 +1056,7 @@ class IgxTouchManager {
1054
1056
  this._pointerId = null;
1055
1057
  this._startTarget = null;
1056
1058
  this._onPointerDown = (event) => {
1057
- if (this._tracking || !this._accepts(event.pointerType)) {
1059
+ if (this._tracking || !this._accepts(event.pointerType) || this._canStart?.(event) === false) {
1058
1060
  return;
1059
1061
  }
1060
1062
  this._startX = event.clientX;
@@ -1073,7 +1075,17 @@ class IgxTouchManager {
1073
1075
  // (e.g. for synthetic events). Capturing is a best-effort enhancement, so ignore it.
1074
1076
  }
1075
1077
  }
1076
- this.callbacks.pointerDown?.(this._createEvent(event));
1078
+ // Let the consumer veto the gesture (e.g. the touch did not start in an active
1079
+ // zone). Returning `false` stops tracking immediately so the `touchmove` listener
1080
+ // does not block normal scrolling and other gestures are not interfered with.
1081
+ if (this.callbacks.pointerDown) {
1082
+ const gesture = this._createEvent(event);
1083
+ this._runInAngular(() => {
1084
+ if (this.callbacks.pointerDown?.(gesture) === false) {
1085
+ this._stopTracking(event.pointerId);
1086
+ }
1087
+ });
1088
+ }
1077
1089
  };
1078
1090
  this._onPointerMove = (event) => {
1079
1091
  if (!this._tracking || event.pointerId !== this._pointerId || !this._accepts(event.pointerType)) {
@@ -1084,8 +1096,13 @@ class IgxTouchManager {
1084
1096
  // A press with no movement (a tap) therefore never raises `panStart`.
1085
1097
  if (!this._panStarted) {
1086
1098
  this._panStarted = true;
1087
- this.callbacks.panStart?.(gesture);
1099
+ if (this.callbacks.panStart) {
1100
+ this._runInAngular(() => this.callbacks.panStart(gesture));
1101
+ }
1088
1102
  }
1103
+ // `panMove` is intentionally invoked outside of the Angular zone (when one is provided)
1104
+ // as it fires for every pointer move and running change detection for each of them
1105
+ // makes continuous dragging lag behind the pointer.
1089
1106
  this.callbacks.panMove?.(gesture);
1090
1107
  };
1091
1108
  this._onPointerUp = (event) => {
@@ -1095,16 +1112,18 @@ class IgxTouchManager {
1095
1112
  this._tracking = false;
1096
1113
  this._pointerId = null;
1097
1114
  const gesture = this._createEvent(event);
1098
- if (this.callbacks.tap && gesture.distance < this._tapThreshold) {
1099
- this.callbacks.tap(gesture);
1100
- return;
1101
- }
1102
- if (this.callbacks.swipe &&
1103
- gesture.velocity > this._swipeVelocityThreshold &&
1104
- Math.abs(gesture.deltaX) > Math.abs(gesture.deltaY)) {
1105
- this.callbacks.swipe(gesture);
1106
- }
1107
- this.callbacks.panEnd?.(gesture);
1115
+ this._runInAngular(() => {
1116
+ if (this.callbacks.tap && gesture.distance < this._tapThreshold) {
1117
+ this.callbacks.tap(gesture);
1118
+ return;
1119
+ }
1120
+ if (this.callbacks.swipe &&
1121
+ gesture.velocity > this._swipeVelocityThreshold &&
1122
+ Math.abs(gesture.deltaX) > Math.abs(gesture.deltaY)) {
1123
+ this.callbacks.swipe(gesture);
1124
+ }
1125
+ this.callbacks.panEnd?.(gesture);
1126
+ });
1108
1127
  };
1109
1128
  this._onPointerCancel = (event) => {
1110
1129
  if (!this._tracking || event.pointerId !== this._pointerId) {
@@ -1112,7 +1131,10 @@ class IgxTouchManager {
1112
1131
  }
1113
1132
  this._tracking = false;
1114
1133
  this._pointerId = null;
1115
- this.callbacks.panCancel?.(this._createEvent(event));
1134
+ if (this.callbacks.panCancel) {
1135
+ const gesture = this._createEvent(event);
1136
+ this._runInAngular(() => this.callbacks.panCancel(gesture));
1137
+ }
1116
1138
  };
1117
1139
  this._onTouchMove = (event) => {
1118
1140
  // Prevent scrolling only while a gesture is actively tracked.
@@ -1124,6 +1146,8 @@ class IgxTouchManager {
1124
1146
  this._setPointerCapture = options.setPointerCapture ?? true;
1125
1147
  this._tapThreshold = options.tapThreshold ?? 0;
1126
1148
  this._swipeVelocityThreshold = options.swipeVelocityThreshold ?? 0.3;
1149
+ this._canStart = options.canStart ?? null;
1150
+ this._ngZone = options.ngZone ?? null;
1127
1151
  // Behave as a noop outside of a browser (e.g. during server-side rendering),
1128
1152
  // mirroring the previous Hammer.js-based manager. Angular's platform-server
1129
1153
  // does not define a global `window`, so pointer events can never occur there
@@ -1134,14 +1158,16 @@ class IgxTouchManager {
1134
1158
  if (!this._supported) {
1135
1159
  return;
1136
1160
  }
1137
- this.target.addEventListener('pointerdown', this._onPointerDown);
1138
- this.target.addEventListener('pointermove', this._onPointerMove);
1139
- this.target.addEventListener('pointerup', this._onPointerUp);
1140
- this.target.addEventListener('pointercancel', this._onPointerCancel);
1141
- // prevents the default scrolling behavior on touch devices while a gesture is tracked
1142
- // necessary on edge pans detected on the body as the browsers cancel the pointer events
1143
- // and trigger a scroll / rubber band effect instead of the pan
1144
- this.target.addEventListener('touchmove', this._onTouchMove, { passive: false });
1161
+ this._runOutsideAngular(() => {
1162
+ this.target.addEventListener('pointerdown', this._onPointerDown);
1163
+ this.target.addEventListener('pointermove', this._onPointerMove);
1164
+ this.target.addEventListener('pointerup', this._onPointerUp);
1165
+ this.target.addEventListener('pointercancel', this._onPointerCancel);
1166
+ // prevents the default scrolling behavior on touch devices while a gesture is tracked
1167
+ // necessary on edge pans detected on the body as the browsers cancel the pointer events
1168
+ // and trigger a scroll / rubber band effect instead of the pan
1169
+ this.target.addEventListener('touchmove', this._onTouchMove, { passive: false });
1170
+ });
1145
1171
  }
1146
1172
  /** Detaches all listeners and stops tracking. */
1147
1173
  destroy() {
@@ -1158,6 +1184,23 @@ class IgxTouchManager {
1158
1184
  _accepts(pointerType) {
1159
1185
  return this._pointerTypes.includes(pointerType);
1160
1186
  }
1187
+ _runOutsideAngular(fn) {
1188
+ if (this._ngZone) {
1189
+ this._ngZone.runOutsideAngular(fn);
1190
+ }
1191
+ else {
1192
+ fn();
1193
+ }
1194
+ }
1195
+ /** Invokes a discrete (low frequency) callback back inside the Angular zone, when one is provided. */
1196
+ _runInAngular(fn) {
1197
+ if (this._ngZone) {
1198
+ this._ngZone.run(fn);
1199
+ }
1200
+ else {
1201
+ fn();
1202
+ }
1203
+ }
1161
1204
  _createEvent(event) {
1162
1205
  const deltaX = event.clientX - this._startX;
1163
1206
  const deltaY = event.clientY - this._startY;
@@ -1184,6 +1227,22 @@ class IgxTouchManager {
1184
1227
  }
1185
1228
  };
1186
1229
  }
1230
+ /** Stops tracking the current gesture and best-effort releases the pointer capture. */
1231
+ _stopTracking(pointerId) {
1232
+ this._tracking = false;
1233
+ this._panStarted = false;
1234
+ this._pointerId = null;
1235
+ this._startTarget = null;
1236
+ if (this._setPointerCapture && typeof this.target.releasePointerCapture === 'function') {
1237
+ try {
1238
+ this.target.releasePointerCapture(pointerId);
1239
+ }
1240
+ catch {
1241
+ // `releasePointerCapture` can throw when the pointer is no longer captured.
1242
+ // Releasing is a best-effort cleanup, so ignore it.
1243
+ }
1244
+ }
1245
+ }
1187
1246
  }
1188
1247
 
1189
1248
  /* csSuppress */