@ship-ui/core 0.22.16 → 0.22.17

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 (66) hide show
  1. package/assets/mcp/components.json +181 -39
  2. package/bin/src/subset.ts +6 -6
  3. package/bin/src/utilities.ts +14 -14
  4. package/fesm2022/ship-ui-core-ship-a11y-keybindings.mjs +4 -87
  5. package/fesm2022/ship-ui-core-ship-a11y-keybindings.mjs.map +1 -1
  6. package/fesm2022/ship-ui-core-ship-accordion.mjs +4 -3
  7. package/fesm2022/ship-ui-core-ship-accordion.mjs.map +1 -1
  8. package/fesm2022/ship-ui-core-ship-alert.mjs +1 -4
  9. package/fesm2022/ship-ui-core-ship-alert.mjs.map +1 -1
  10. package/fesm2022/ship-ui-core-ship-blueprint.mjs +8 -10
  11. package/fesm2022/ship-ui-core-ship-blueprint.mjs.map +1 -1
  12. package/fesm2022/ship-ui-core-ship-checkbox.mjs +3 -2
  13. package/fesm2022/ship-ui-core-ship-checkbox.mjs.map +1 -1
  14. package/fesm2022/ship-ui-core-ship-color-picker.mjs +66 -62
  15. package/fesm2022/ship-ui-core-ship-color-picker.mjs.map +1 -1
  16. package/fesm2022/ship-ui-core-ship-datepicker.mjs +8 -12
  17. package/fesm2022/ship-ui-core-ship-datepicker.mjs.map +1 -1
  18. package/fesm2022/ship-ui-core-ship-editor.mjs +0 -42
  19. package/fesm2022/ship-ui-core-ship-editor.mjs.map +1 -1
  20. package/fesm2022/ship-ui-core-ship-form-field.mjs +0 -1
  21. package/fesm2022/ship-ui-core-ship-form-field.mjs.map +1 -1
  22. package/fesm2022/ship-ui-core-ship-kbd.mjs +0 -6
  23. package/fesm2022/ship-ui-core-ship-kbd.mjs.map +1 -1
  24. package/fesm2022/ship-ui-core-ship-list-item-swipe.mjs +241 -0
  25. package/fesm2022/ship-ui-core-ship-list-item-swipe.mjs.map +1 -0
  26. package/fesm2022/ship-ui-core-ship-menu.mjs +7 -10
  27. package/fesm2022/ship-ui-core-ship-menu.mjs.map +1 -1
  28. package/fesm2022/ship-ui-core-ship-popover.mjs +1 -20
  29. package/fesm2022/ship-ui-core-ship-popover.mjs.map +1 -1
  30. package/fesm2022/ship-ui-core-ship-radio.mjs +3 -2
  31. package/fesm2022/ship-ui-core-ship-radio.mjs.map +1 -1
  32. package/fesm2022/ship-ui-core-ship-range-slider.mjs +7 -9
  33. package/fesm2022/ship-ui-core-ship-range-slider.mjs.map +1 -1
  34. package/fesm2022/ship-ui-core-ship-select.mjs.map +1 -1
  35. package/fesm2022/ship-ui-core-ship-sidenav.mjs +2 -2
  36. package/fesm2022/ship-ui-core-ship-sidenav.mjs.map +1 -1
  37. package/fesm2022/ship-ui-core-ship-sortable.mjs +262 -68
  38. package/fesm2022/ship-ui-core-ship-sortable.mjs.map +1 -1
  39. package/fesm2022/ship-ui-core-ship-spotlight.mjs +0 -11
  40. package/fesm2022/ship-ui-core-ship-spotlight.mjs.map +1 -1
  41. package/fesm2022/ship-ui-core-ship-stepper.mjs +1 -1
  42. package/fesm2022/ship-ui-core-ship-stepper.mjs.map +1 -1
  43. package/fesm2022/ship-ui-core-ship-table.mjs +4 -5
  44. package/fesm2022/ship-ui-core-ship-table.mjs.map +1 -1
  45. package/fesm2022/ship-ui-core-ship-toggle.mjs +3 -2
  46. package/fesm2022/ship-ui-core-ship-toggle.mjs.map +1 -1
  47. package/fesm2022/ship-ui-core-ship-tree.mjs +1 -9
  48. package/fesm2022/ship-ui-core-ship-tree.mjs.map +1 -1
  49. package/fesm2022/ship-ui-core.mjs +37 -53
  50. package/fesm2022/ship-ui-core.mjs.map +1 -1
  51. package/package.json +5 -1
  52. package/types/ship-ui-core-ship-a11y-keybindings.d.ts +0 -55
  53. package/types/ship-ui-core-ship-accordion.d.ts +7 -7
  54. package/types/ship-ui-core-ship-blueprint.d.ts +1 -1
  55. package/types/ship-ui-core-ship-checkbox.d.ts +2 -3
  56. package/types/ship-ui-core-ship-color-picker.d.ts +1 -25
  57. package/types/ship-ui-core-ship-datepicker.d.ts +0 -3
  58. package/types/ship-ui-core-ship-editor.d.ts +10 -10
  59. package/types/ship-ui-core-ship-list-item-swipe.d.ts +25 -0
  60. package/types/ship-ui-core-ship-menu.d.ts +1 -2
  61. package/types/ship-ui-core-ship-radio.d.ts +2 -3
  62. package/types/ship-ui-core-ship-range-slider.d.ts +6 -6
  63. package/types/ship-ui-core-ship-sortable.d.ts +31 -9
  64. package/types/ship-ui-core-ship-toggle.d.ts +2 -3
  65. package/types/ship-ui-core-ship-tree.d.ts +20 -25
  66. package/types/ship-ui-core.d.ts +17 -24
@@ -1,13 +1,27 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, DOCUMENT, ElementRef, Renderer2, signal, input, model, output, effect, HostListener, Directive, computed } from '@angular/core';
2
+ import { Injectable, inject, DOCUMENT, ElementRef, Renderer2, signal, input, model, output, effect, HostListener, Directive, computed } from '@angular/core';
3
3
  import { isObservable, firstValueFrom } from 'rxjs';
4
4
 
5
- var _a;
5
+ class ShipSortableService {
6
+ constructor() {
7
+ this.activeSource = null;
8
+ this.activeDraggedElement = null;
9
+ this.activeTarget = null;
10
+ this.activeInstances = new Set();
11
+ }
12
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: ShipSortableService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
13
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: ShipSortableService, providedIn: 'root' }); }
14
+ }
15
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: ShipSortableService, decorators: [{
16
+ type: Injectable,
17
+ args: [{
18
+ providedIn: 'root',
19
+ }]
20
+ }] });
6
21
  function createSortableManager(signals, config) {
7
22
  const isSingle = typeof signals === 'function';
8
23
  return {
9
24
  async drop(event) {
10
- // 1. Await API Authorization (RxJS or Promises)
11
25
  if (config?.onBeforeDrop) {
12
26
  const result = config.onBeforeDrop(event);
13
27
  let accept = false;
@@ -21,12 +35,10 @@ function createSortableManager(signals, config) {
21
35
  accept = result;
22
36
  }
23
37
  if (!accept)
24
- return; // Drop rejected, UI stays exactly as it was
38
+ return;
25
39
  }
26
- // 2. Perform UI Signal Update
27
40
  const isCrossDrop = event.previousContainer !== event.container;
28
41
  if (!isCrossDrop) {
29
- // Internal Reorder (moveIndex)
30
42
  let targetSignal;
31
43
  if (isSingle) {
32
44
  targetSignal = signals;
@@ -40,7 +52,6 @@ function createSortableManager(signals, config) {
40
52
  }
41
53
  }
42
54
  else {
43
- // Cross DropTransfer
44
55
  if (isSingle) {
45
56
  console.warn('Cross drops require a dictionary of signals in createSortableManager');
46
57
  return;
@@ -66,6 +77,7 @@ function createSortableManager(signals, config) {
66
77
  }
67
78
  class ShipSortable {
68
79
  constructor() {
80
+ this.#sortableService = inject(ShipSortableService);
69
81
  this.#document = inject(DOCUMENT);
70
82
  this.#selfEl = inject((ElementRef));
71
83
  this.#renderer = inject(Renderer2);
@@ -79,6 +91,10 @@ class ShipSortable {
79
91
  ...(ngDevMode ? [{ debugName: "sortingMode" }] : /* istanbul ignore next */ []));
80
92
  this.treeItems = model([], /* @ts-ignore */
81
93
  ...(ngDevMode ? [{ debugName: "treeItems" }] : /* istanbul ignore next */ []));
94
+ this.touchEnabled = input(false, /* @ts-ignore */
95
+ ...(ngDevMode ? [{ debugName: "touchEnabled" }] : /* istanbul ignore next */ []));
96
+ this.touchActivation = input('longpress', /* @ts-ignore */
97
+ ...(ngDevMode ? [{ debugName: "touchActivation" }] : /* istanbul ignore next */ []));
82
98
  this.sortDrop = output();
83
99
  this.afterDrop = output();
84
100
  this.crossDrop = output();
@@ -98,6 +114,13 @@ class ShipSortable {
98
114
  this.abortController = null;
99
115
  this.isDropping = false;
100
116
  this.isCrossTarget = false;
117
+ this.touchDragTimer = null;
118
+ this.touchStartCoordinates = null;
119
+ this.isTouchDragging = false;
120
+ this.touchGhostEl = null;
121
+ this.touchOffset = { x: 0, y: 0 };
122
+ this.#boundTouchMove = this.onTouchMove.bind(this);
123
+ this.#boundTouchEnd = this.onTouchEnd.bind(this);
101
124
  this.draggingEffect = effect(() => {
102
125
  if (this.sortingMode() === 'tree') {
103
126
  return;
@@ -159,6 +182,12 @@ class ShipSortable {
159
182
  for (const el of els) {
160
183
  el.addEventListener('dragstart', (e) => this.dragStart(e), { signal: this.abortController.signal });
161
184
  el.addEventListener('dragend', () => this.dragEnd(), { signal: this.abortController.signal });
185
+ if (this.touchEnabled()) {
186
+ el.addEventListener('touchstart', (e) => this.onTouchStart(e, el), {
187
+ signal: this.abortController.signal,
188
+ passive: false,
189
+ });
190
+ }
162
191
  }
163
192
  }, /* @ts-ignore */
164
193
  ...(ngDevMode ? [{ debugName: "draggablesEffect" }] : /* istanbul ignore next */ []));
@@ -171,11 +200,11 @@ class ShipSortable {
171
200
  if (this.isDropping) {
172
201
  this.isDropping = false;
173
202
  this.#cleanupDragState();
174
- if (_a.activeTarget === this) {
175
- _a.activeTarget = null;
203
+ if (this.#sortableService.activeTarget === this) {
204
+ this.#sortableService.activeTarget = null;
176
205
  }
177
- if (_a.activeSource === this) {
178
- _a.activeSource = null;
206
+ if (this.#sortableService.activeSource === this) {
207
+ this.#sortableService.activeSource = null;
179
208
  }
180
209
  }
181
210
  }
@@ -183,13 +212,13 @@ class ShipSortable {
183
212
  })
184
213
  : undefined;
185
214
  }
215
+ #sortableService;
186
216
  #document;
187
217
  #selfEl;
188
218
  #renderer;
189
219
  #crossSpacerEl;
190
- static { this.activeSource = null; }
191
- static { this.activeDraggedElement = null; }
192
- static { this.activeTarget = null; }
220
+ #boundTouchMove;
221
+ #boundTouchEnd;
193
222
  getIndexOfElement(element) {
194
223
  return this.dragables().findIndex((el) => el === element);
195
224
  }
@@ -210,9 +239,9 @@ class ShipSortable {
210
239
  }
211
240
  }
212
241
  e.dataTransfer.effectAllowed = 'move';
213
- _a.activeSource = this;
214
- _a.activeDraggedElement = draggedElement;
215
- _a.activeTarget = this;
242
+ this.#sortableService.activeSource = this;
243
+ this.#sortableService.activeDraggedElement = draggedElement;
244
+ this.#sortableService.activeTarget = this;
216
245
  this.isCrossTarget = false;
217
246
  const containerRect = this.#selfEl.nativeElement.getBoundingClientRect();
218
247
  const container = this.#selfEl.nativeElement;
@@ -255,28 +284,35 @@ class ShipSortable {
255
284
  }
256
285
  }
257
286
  ngOnInit() {
287
+ this.#sortableService.activeInstances.add(this);
258
288
  if (typeof MutationObserver !== 'undefined') {
259
289
  this.#dragableObserver.observe(this.#selfEl.nativeElement, { childList: true });
260
290
  }
261
291
  }
262
292
  dragEnter(e) {
263
- if (!_a.activeSource || _a.activeSource === this)
293
+ this.processDragEnter();
294
+ }
295
+ processDragEnter() {
296
+ if (!this.#sortableService.activeSource || this.#sortableService.activeSource === this)
264
297
  return;
265
- const sourceGroup = _a.activeSource.sortableGroup();
298
+ const sourceGroup = this.#sortableService.activeSource.sortableGroup();
266
299
  const currentGroup = this.sortableGroup();
267
- const sourceManager = _a.activeSource.shSortable();
300
+ const sourceManager = this.#sortableService.activeSource.shSortable();
268
301
  const currentManager = this.shSortable();
269
302
  const isSameGroup = !!(sourceGroup && currentGroup && sourceGroup === currentGroup);
270
303
  const isSameManager = !!(sourceManager?.drop && currentManager?.drop && sourceManager === currentManager);
271
304
  if (isSameGroup || isSameManager) {
272
- _a.activeTarget = this;
273
- _a.activeSource.dragToIndex.set(-1);
305
+ if (this.#sortableService.activeTarget && this.#sortableService.activeTarget !== this && this.#sortableService.activeTarget !== this.#sortableService.activeSource) {
306
+ this.#sortableService.activeTarget.processDragLeave(0, 0, null, true);
307
+ }
308
+ this.#sortableService.activeTarget = this;
309
+ this.#sortableService.activeSource.dragToIndex.set(-1);
274
310
  // Setup Target Placeholder if we are just entering
275
311
  if (!this.isCrossTarget) {
276
312
  this.isCrossTarget = true;
277
313
  this.#renderer.addClass(this.#selfEl.nativeElement, 'dragging');
278
314
  // Compute cross-target positions by temporarily appending the active ghost to measure layout flow
279
- const sourceElement = _a.activeDraggedElement;
315
+ const sourceElement = this.#sortableService.activeDraggedElement;
280
316
  const tempElement = sourceElement.cloneNode(true);
281
317
  this.#renderer.setStyle(tempElement, 'transform', '');
282
318
  // Ensure it doesn't have the original ghost state yet to measure flow without its potential transition scaling
@@ -307,39 +343,47 @@ class ShipSortable {
307
343
  }
308
344
  }
309
345
  dragLeave(e) {
310
- if (!_a.activeSource || _a.activeSource === this)
346
+ this.processDragLeave(e.clientX, e.clientY, e.relatedTarget);
347
+ }
348
+ processDragLeave(clientX, clientY, relatedTarget, force = false) {
349
+ if (!this.#sortableService.activeSource || this.#sortableService.activeSource === this)
311
350
  return;
312
- if (e.relatedTarget) {
313
- if (this.#selfEl.nativeElement.contains(e.relatedTarget)) {
314
- return;
351
+ if (!force) {
352
+ if (relatedTarget) {
353
+ if (this.#selfEl.nativeElement.contains(relatedTarget)) {
354
+ return;
355
+ }
356
+ }
357
+ else {
358
+ const rect = this.#selfEl.nativeElement.getBoundingClientRect();
359
+ const isOutside = clientX < rect.left || clientX > rect.right || clientY < rect.top || clientY > rect.bottom;
360
+ if (!isOutside)
361
+ return;
315
362
  }
316
- }
317
- else {
318
- const rect = this.#selfEl.nativeElement.getBoundingClientRect();
319
- const isOutside = e.clientX < rect.left || e.clientX > rect.right || e.clientY < rect.top || e.clientY > rect.bottom;
320
- if (!isOutside)
321
- return;
322
363
  }
323
364
  if (this.isCrossTarget) {
324
365
  this.#cleanupDragState();
325
- if (_a.activeTarget === this) {
326
- _a.activeTarget = _a.activeSource;
366
+ if (this.#sortableService.activeTarget === this) {
367
+ this.#sortableService.activeTarget = this.#sortableService.activeSource;
327
368
  }
328
369
  }
329
370
  }
330
371
  dragOver(e) {
331
372
  e.preventDefault();
332
373
  e.dataTransfer.dropEffect = 'move';
333
- if (_a.activeTarget !== this)
374
+ this.processDragOver(e.clientX, e.clientY, e.target);
375
+ }
376
+ processDragOver(clientX, clientY, targetElementUnderTouch) {
377
+ if (this.#sortableService.activeTarget !== this)
334
378
  return;
335
379
  if (this.sortingMode() === 'tree') {
336
- const targetElement = e.target;
337
- const hoveredDraggable = targetElement.closest('[draggable]');
380
+ const targetElement = targetElementUnderTouch || this.#document.elementFromPoint(clientX, clientY);
381
+ const hoveredDraggable = targetElement?.closest('[draggable]');
338
382
  if (hoveredDraggable && this.#selfEl.nativeElement.contains(hoveredDraggable)) {
339
383
  const targetIdx = this.getIndexOfElement(hoveredDraggable);
340
384
  if (targetIdx !== -1) {
341
385
  const rect = hoveredDraggable.getBoundingClientRect();
342
- const relativeY = (e.clientY - rect.top) / rect.height;
386
+ const relativeY = (clientY - rect.top) / rect.height;
343
387
  const isFolder = hoveredDraggable.hasAttribute('sortable-folder') ||
344
388
  hoveredDraggable.getAttribute('sortable-folder') === 'true' ||
345
389
  hoveredDraggable.hasAttribute('sortable-dir') ||
@@ -385,8 +429,8 @@ class ShipSortable {
385
429
  const container = this.#selfEl.nativeElement;
386
430
  const containerRect = container.getBoundingClientRect();
387
431
  // Convert viewport coordinates to container-relative coordinate space
388
- const mouseX = e.clientX - containerRect.left - container.clientLeft + container.scrollLeft;
389
- const mouseY = e.clientY - containerRect.top - container.clientTop + container.scrollTop;
432
+ const mouseX = clientX - containerRect.left - container.clientLeft + container.scrollLeft;
433
+ const mouseY = clientY - containerRect.top - container.clientTop + container.scrollTop;
390
434
  let closestSlotIndex = -1;
391
435
  let minDistance = Infinity;
392
436
  const positions = this.initialPositions();
@@ -404,6 +448,156 @@ class ShipSortable {
404
448
  this.dragToIndex.set(closestSlotIndex);
405
449
  }
406
450
  }
451
+ onTouchStart(e, el) {
452
+ if (!this.touchEnabled() || this.touchActivation() === 'none') {
453
+ return;
454
+ }
455
+ const touch = e.touches[0];
456
+ const targetEl = touch.target;
457
+ const isSortingHandle = targetEl.hasAttribute('sort-handle') || targetEl.closest('[sort-handle]') !== null;
458
+ const hasHandle = el.querySelector('[sort-handle]') !== null;
459
+ if (hasHandle && !isSortingHandle) {
460
+ return;
461
+ }
462
+ if (this.touchActivation() === 'handle') {
463
+ if (!isSortingHandle) {
464
+ return;
465
+ }
466
+ e.preventDefault();
467
+ this.startTouchDrag(touch, el);
468
+ }
469
+ else if (this.touchActivation() === 'longpress') {
470
+ this.touchStartCoordinates = { x: touch.clientX, y: touch.clientY };
471
+ this.#document.addEventListener('touchmove', this.#boundTouchMove, { passive: false });
472
+ this.#document.addEventListener('touchend', this.#boundTouchEnd, { passive: false });
473
+ this.#document.addEventListener('touchcancel', this.#boundTouchEnd, { passive: false });
474
+ this.touchDragTimer = setTimeout(() => {
475
+ this.startTouchDrag(touch, el);
476
+ }, 300);
477
+ }
478
+ }
479
+ startTouchDrag(touch, el) {
480
+ this.isTouchDragging = true;
481
+ this.#sortableService.activeSource = this;
482
+ this.#sortableService.activeDraggedElement = el;
483
+ this.#sortableService.activeTarget = this;
484
+ this.isCrossTarget = false;
485
+ const containerRect = this.#selfEl.nativeElement.getBoundingClientRect();
486
+ const container = this.#selfEl.nativeElement;
487
+ const positions = Array.from(this.dragables()).map((item) => {
488
+ const rect = item.getBoundingClientRect();
489
+ return {
490
+ x: rect.left - containerRect.left - container.clientLeft + container.scrollLeft,
491
+ y: rect.top - containerRect.top - container.clientTop + container.scrollTop,
492
+ width: rect.width,
493
+ height: rect.height,
494
+ };
495
+ });
496
+ this.initialPositions.set(positions);
497
+ const rect = el.getBoundingClientRect();
498
+ this.touchOffset = {
499
+ x: touch.clientX - rect.left,
500
+ y: touch.clientY - rect.top,
501
+ };
502
+ const ghost = el.cloneNode(true);
503
+ ghost.style.position = 'fixed';
504
+ ghost.style.width = `${rect.width}px`;
505
+ ghost.style.height = `${rect.height}px`;
506
+ ghost.style.left = `${rect.left}px`;
507
+ ghost.style.top = `${rect.top}px`;
508
+ ghost.style.pointerEvents = 'none';
509
+ ghost.style.zIndex = '9999';
510
+ ghost.style.opacity = '0.8';
511
+ ghost.style.boxShadow = '0 5px 15px rgba(0,0,0,0.3)';
512
+ ghost.style.margin = '0';
513
+ ghost.style.transform = '';
514
+ ghost.classList.add('sortable-ghost-touch');
515
+ this.#document.body.appendChild(ghost);
516
+ this.touchGhostEl = ghost;
517
+ const draggedElementIndex = this.getIndexOfElement(el);
518
+ this.dragStartIndex.set(draggedElementIndex);
519
+ this.dragToIndex.set(draggedElementIndex);
520
+ this.#renderer.addClass(el, 'sortable-ghost');
521
+ this.#renderer.addClass(this.#selfEl.nativeElement, 'dragging');
522
+ if (this.touchActivation() === 'handle') {
523
+ this.touchStartCoordinates = { x: touch.clientX, y: touch.clientY };
524
+ this.#document.addEventListener('touchmove', this.#boundTouchMove, { passive: false });
525
+ this.#document.addEventListener('touchend', this.#boundTouchEnd, { passive: false });
526
+ this.#document.addEventListener('touchcancel', this.#boundTouchEnd, { passive: false });
527
+ }
528
+ }
529
+ onTouchMove(e) {
530
+ const touch = e.touches[0];
531
+ const clientX = touch.clientX;
532
+ const clientY = touch.clientY;
533
+ if (!this.isTouchDragging) {
534
+ if (this.touchStartCoordinates) {
535
+ const dx = clientX - this.touchStartCoordinates.x;
536
+ const dy = clientY - this.touchStartCoordinates.y;
537
+ if (Math.hypot(dx, dy) > 8) {
538
+ this.cancelTouchDrag();
539
+ }
540
+ }
541
+ return;
542
+ }
543
+ e.preventDefault();
544
+ if (this.touchGhostEl) {
545
+ const x = clientX - this.touchOffset.x;
546
+ const y = clientY - this.touchOffset.y;
547
+ this.touchGhostEl.style.left = `${x}px`;
548
+ this.touchGhostEl.style.top = `${y}px`;
549
+ }
550
+ const elementUnderTouch = this.#document.elementFromPoint(clientX, clientY);
551
+ let targetInstance = null;
552
+ if (elementUnderTouch) {
553
+ for (const instance of this.#sortableService.activeInstances) {
554
+ if (instance.#selfEl.nativeElement === elementUnderTouch || instance.#selfEl.nativeElement.contains(elementUnderTouch)) {
555
+ targetInstance = instance;
556
+ break;
557
+ }
558
+ }
559
+ }
560
+ if (targetInstance) {
561
+ if (this.#sortableService.activeTarget !== targetInstance) {
562
+ if (this.#sortableService.activeTarget) {
563
+ this.#sortableService.activeTarget.processDragLeave(clientX, clientY, null, true);
564
+ }
565
+ this.#sortableService.activeTarget = targetInstance;
566
+ targetInstance.processDragEnter();
567
+ }
568
+ this.#sortableService.activeTarget.processDragOver(clientX, clientY, elementUnderTouch);
569
+ }
570
+ else {
571
+ if (this.#sortableService.activeTarget && this.#sortableService.activeTarget !== this.#sortableService.activeSource) {
572
+ this.#sortableService.activeTarget.processDragLeave(clientX, clientY, null, true);
573
+ }
574
+ }
575
+ }
576
+ onTouchEnd(e) {
577
+ const wasDragging = this.isTouchDragging;
578
+ this.cancelTouchDrag();
579
+ if (wasDragging) {
580
+ this.isTouchDragging = false;
581
+ if (this.#sortableService.activeTarget) {
582
+ this.#sortableService.activeTarget.drop();
583
+ }
584
+ if (this.touchGhostEl) {
585
+ this.touchGhostEl.remove();
586
+ this.touchGhostEl = null;
587
+ }
588
+ this.dragEnd();
589
+ }
590
+ }
591
+ cancelTouchDrag() {
592
+ if (this.touchDragTimer) {
593
+ clearTimeout(this.touchDragTimer);
594
+ this.touchDragTimer = null;
595
+ }
596
+ this.touchStartCoordinates = null;
597
+ this.#document.removeEventListener('touchmove', this.#boundTouchMove);
598
+ this.#document.removeEventListener('touchend', this.#boundTouchEnd);
599
+ this.#document.removeEventListener('touchcancel', this.#boundTouchEnd);
600
+ }
407
601
  #clearTreeHoverClasses() {
408
602
  const dragables = this.dragables();
409
603
  for (const el of dragables) {
@@ -432,17 +626,17 @@ class ShipSortable {
432
626
  return targetVisualIndex;
433
627
  }
434
628
  drop() {
435
- if (!_a.activeSource)
629
+ if (!this.#sortableService.activeSource)
436
630
  return;
437
631
  // Immediately kill drag transitions before any signal updates
438
- this.#renderer.removeClass(_a.activeSource.#selfEl.nativeElement, 'dragging');
632
+ this.#renderer.removeClass(this.#sortableService.activeSource.#selfEl.nativeElement, 'dragging');
439
633
  this.#renderer.removeClass(this.#selfEl.nativeElement, 'dragging');
440
634
  if (this.sortingMode() === 'tree') {
441
635
  this.isDropping = true;
442
- if (_a.activeSource !== this) {
443
- _a.activeSource.isDropping = true;
636
+ if (this.#sortableService.activeSource !== this) {
637
+ this.#sortableService.activeSource.isDropping = true;
444
638
  }
445
- const prevIdx = _a.activeSource.dragStartIndex();
639
+ const prevIdx = this.#sortableService.activeSource.dragStartIndex();
446
640
  const currIdx = this.dragToIndex();
447
641
  const pos = this.treeHoverPosition();
448
642
  if (prevIdx !== -1 && currIdx !== -1 && pos) {
@@ -460,12 +654,12 @@ class ShipSortable {
460
654
  }
461
655
  }
462
656
  this.#cleanupDragState();
463
- if (_a.activeSource !== this) {
464
- _a.activeSource.#cleanupDragState();
657
+ if (this.#sortableService.activeSource !== this) {
658
+ this.#sortableService.activeSource.#cleanupDragState();
465
659
  }
466
660
  return;
467
661
  }
468
- if (_a.activeSource === this) {
662
+ if (this.#sortableService.activeSource === this) {
469
663
  // Internal Drop
470
664
  if (this.dragStartIndex() !== -1 && this.dragToIndex() !== -1 && this.dragStartIndex() !== this.dragToIndex()) {
471
665
  this.isDropping = true;
@@ -484,14 +678,14 @@ class ShipSortable {
484
678
  }
485
679
  }
486
680
  }
487
- else if (_a.activeTarget === this && this.isCrossTarget) {
681
+ else if (this.#sortableService.activeTarget === this && this.isCrossTarget) {
488
682
  // Cross Drop
489
683
  this.isDropping = true;
490
- _a.activeSource.isDropping = true;
684
+ this.#sortableService.activeSource.isDropping = true;
491
685
  const event = {
492
- previousContainer: _a.activeSource,
686
+ previousContainer: this.#sortableService.activeSource,
493
687
  container: this,
494
- previousIndex: _a.activeSource.dragStartIndex(),
688
+ previousIndex: this.#sortableService.activeSource.dragStartIndex(),
495
689
  currentIndex: this.dragToIndex(),
496
690
  };
497
691
  if (this.shSortable()?.drop) {
@@ -500,26 +694,26 @@ class ShipSortable {
500
694
  else {
501
695
  this.sortDrop.emit(event);
502
696
  this.crossDrop.emit({
503
- previousContainer: _a.activeSource,
697
+ previousContainer: this.#sortableService.activeSource,
504
698
  currentContainer: this,
505
- previousIndex: _a.activeSource.dragStartIndex(),
699
+ previousIndex: this.#sortableService.activeSource.dragStartIndex(),
506
700
  currentIndex: this.dragToIndex(),
507
701
  });
508
702
  }
509
703
  }
510
704
  }
511
705
  dragEnd() {
512
- if (_a.activeSource) {
513
- _a.activeSource.#renderer.removeClass(_a.activeSource.#selfEl.nativeElement, 'dragging');
514
- _a.activeSource.#cleanupDragState();
706
+ if (this.#sortableService.activeSource) {
707
+ this.#sortableService.activeSource.#renderer.removeClass(this.#sortableService.activeSource.#selfEl.nativeElement, 'dragging');
708
+ this.#sortableService.activeSource.#cleanupDragState();
515
709
  }
516
- if (_a.activeTarget && _a.activeTarget !== _a.activeSource) {
517
- _a.activeTarget.#renderer.removeClass(_a.activeTarget.#selfEl.nativeElement, 'dragging');
518
- _a.activeTarget.#cleanupDragState();
710
+ if (this.#sortableService.activeTarget && this.#sortableService.activeTarget !== this.#sortableService.activeSource) {
711
+ this.#sortableService.activeTarget.#renderer.removeClass(this.#sortableService.activeTarget.#selfEl.nativeElement, 'dragging');
712
+ this.#sortableService.activeTarget.#cleanupDragState();
519
713
  }
520
- _a.activeSource = null;
521
- _a.activeTarget = null;
522
- _a.activeDraggedElement = null;
714
+ this.#sortableService.activeSource = null;
715
+ this.#sortableService.activeTarget = null;
716
+ this.#sortableService.activeDraggedElement = null;
523
717
  }
524
718
  #cleanupDragState() {
525
719
  this.#renderer.removeClass(this.#selfEl.nativeElement, 'dragging');
@@ -549,13 +743,13 @@ class ShipSortable {
549
743
  }
550
744
  #dragableObserver;
551
745
  ngOnDestroy() {
746
+ this.#sortableService.activeInstances.delete(this);
552
747
  this.#dragableObserver?.disconnect();
553
748
  this.abortController?.abort();
554
749
  }
555
750
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: ShipSortable, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
556
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.0", type: ShipSortable, isStandalone: true, selector: "[shSortable]", inputs: { shSortable: { classPropertyName: "shSortable", publicName: "shSortable", isSignal: true, isRequired: false, transformFunction: null }, sortableGroup: { classPropertyName: "sortableGroup", publicName: "sortableGroup", isSignal: true, isRequired: false, transformFunction: null }, sortingMode: { classPropertyName: "sortingMode", publicName: "sortingMode", isSignal: true, isRequired: false, transformFunction: null }, treeItems: { classPropertyName: "treeItems", publicName: "treeItems", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { treeItems: "treeItemsChange", sortDrop: "sortDrop", afterDrop: "afterDrop", crossDrop: "crossDrop", treeDrop: "treeDrop" }, host: { listeners: { "dragenter": "dragEnter($event)", "dragleave": "dragLeave($event)", "dragover": "dragOver($event)", "drop": "drop()" }, properties: { "class.sh-sortable-tree": "sortingMode() === 'tree'" }, classAttribute: "sh-sortable" }, ngImport: i0 }); }
751
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.0", type: ShipSortable, isStandalone: true, selector: "[shSortable]", inputs: { shSortable: { classPropertyName: "shSortable", publicName: "shSortable", isSignal: true, isRequired: false, transformFunction: null }, sortableGroup: { classPropertyName: "sortableGroup", publicName: "sortableGroup", isSignal: true, isRequired: false, transformFunction: null }, sortingMode: { classPropertyName: "sortingMode", publicName: "sortingMode", isSignal: true, isRequired: false, transformFunction: null }, treeItems: { classPropertyName: "treeItems", publicName: "treeItems", isSignal: true, isRequired: false, transformFunction: null }, touchEnabled: { classPropertyName: "touchEnabled", publicName: "touchEnabled", isSignal: true, isRequired: false, transformFunction: null }, touchActivation: { classPropertyName: "touchActivation", publicName: "touchActivation", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { treeItems: "treeItemsChange", sortDrop: "sortDrop", afterDrop: "afterDrop", crossDrop: "crossDrop", treeDrop: "treeDrop" }, host: { listeners: { "dragenter": "dragEnter($event)", "dragleave": "dragLeave($event)", "dragover": "dragOver($event)", "drop": "drop()" }, properties: { "class.sh-sortable-tree": "sortingMode() === 'tree'" }, classAttribute: "sh-sortable" }, ngImport: i0 }); }
557
752
  }
558
- _a = ShipSortable;
559
753
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: ShipSortable, decorators: [{
560
754
  type: Directive,
561
755
  args: [{
@@ -566,7 +760,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImpor
566
760
  '[class.sh-sortable-tree]': "sortingMode() === 'tree'",
567
761
  },
568
762
  }]
569
- }], propDecorators: { shSortable: [{ type: i0.Input, args: [{ isSignal: true, alias: "shSortable", required: false }] }], sortableGroup: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortableGroup", required: false }] }], sortingMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortingMode", required: false }] }], treeItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "treeItems", required: false }] }, { type: i0.Output, args: ["treeItemsChange"] }], sortDrop: [{ type: i0.Output, args: ["sortDrop"] }], afterDrop: [{ type: i0.Output, args: ["afterDrop"] }], crossDrop: [{ type: i0.Output, args: ["crossDrop"] }], treeDrop: [{ type: i0.Output, args: ["treeDrop"] }], dragEnter: [{
763
+ }], propDecorators: { shSortable: [{ type: i0.Input, args: [{ isSignal: true, alias: "shSortable", required: false }] }], sortableGroup: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortableGroup", required: false }] }], sortingMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortingMode", required: false }] }], treeItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "treeItems", required: false }] }, { type: i0.Output, args: ["treeItemsChange"] }], touchEnabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "touchEnabled", required: false }] }], touchActivation: [{ type: i0.Input, args: [{ isSignal: true, alias: "touchActivation", required: false }] }], sortDrop: [{ type: i0.Output, args: ["sortDrop"] }], afterDrop: [{ type: i0.Output, args: ["afterDrop"] }], crossDrop: [{ type: i0.Output, args: ["crossDrop"] }], treeDrop: [{ type: i0.Output, args: ["treeDrop"] }], dragEnter: [{
570
764
  type: HostListener,
571
765
  args: ['dragenter', ['$event']]
572
766
  }], dragLeave: [{
@@ -714,5 +908,5 @@ function createTreeSortableManager(nodesSignal, config) {
714
908
  * Generated bundle index. Do not edit.
715
909
  */
716
910
 
717
- export { ShipSortable, createSortableManager, createTreeSortableManager, moveIndex, transferArrayItem };
911
+ export { ShipSortable, ShipSortableService, createSortableManager, createTreeSortableManager, moveIndex, transferArrayItem };
718
912
  //# sourceMappingURL=ship-ui-core-ship-sortable.mjs.map