@ionic/core 8.8.7-dev.11778163906.173cadb1 → 8.8.7-dev.11778599050.191a48e3

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.
@@ -0,0 +1,211 @@
1
+ /**
2
+ * Convert a pixels given value into rem
3
+ *
4
+ * @param pixels - Value in pixels to be converted (i.e. px)
5
+ * @param context (optional) - Baseline value
6
+ */
7
+ /**
8
+ * Convert a font size to a dynamic font size.
9
+ * Fonts that participate in Dynamic Type should use
10
+ * dynamic font sizes.
11
+ * @param size - The initial font size including the unit (i.e. px or pt)
12
+ * @param unit (optional) - The unit to convert to. Use this if you want to
13
+ * convert to a unit other than $baselineUnit.
14
+ */
15
+ /**
16
+ * Convert a font size to a dynamic font size but impose
17
+ * a maximum font size.
18
+ * @param size - The initial font size including the unit (i.e. px or pt)
19
+ * @param maxScale - The maximum scale of the font (i.e. 2.5 for a maximum 250% scale).
20
+ * @param unit (optional) - The unit to convert the initial font size to. Use this if you want to
21
+ * convert to a unit other than $baselineUnit.
22
+ */
23
+ /**
24
+ * Convert a font size to a dynamic font size but impose
25
+ * a minimum font size.
26
+ * @param size - The initial font size including the unit (i.e. px or pt)
27
+ * @param minScale - The minimum scale of the font (i.e. 0.8 for a minimum 80% scale).
28
+ * @param unit (optional) - The unit to convert the initial font size to. Use this if you want to
29
+ * convert to a unit other than $baselineUnit.
30
+ */
31
+ /**
32
+ * Convert a font size to a dynamic font size but impose
33
+ * maximum and minimum font sizes.
34
+ * @param size - The initial font size including the unit (i.e. px or pt)
35
+ * @param minScale - The minimum scale of the font (i.e. 0.8 for a minimum 80% scale).
36
+ * @param maxScale - The maximum scale of the font (i.e. 2.5 for a maximum 250% scale).
37
+ * @param unit (optional) - The unit to convert the initial font size to. Use this if you want to
38
+ * convert to a unit other than $baselineUnit.
39
+ */
40
+ /**
41
+ * A heuristic that applies CSS to tablet
42
+ * viewports.
43
+ *
44
+ * Usage:
45
+ * @include tablet-viewport() {
46
+ * :host {
47
+ * background-color: green;
48
+ * }
49
+ * }
50
+ */
51
+ /**
52
+ * A heuristic that applies CSS to mobile
53
+ * viewports (i.e. phones, not tablets).
54
+ *
55
+ * Usage:
56
+ * @include mobile-viewport() {
57
+ * :host {
58
+ * background-color: blue;
59
+ * }
60
+ * }
61
+ */
62
+ ion-item-sliding {
63
+ display: block;
64
+ position: relative;
65
+ width: 100%;
66
+ overflow: hidden;
67
+ user-select: none;
68
+ }
69
+
70
+ ion-item-sliding .item {
71
+ user-select: none;
72
+ }
73
+
74
+ .item-sliding-closing ion-item-options {
75
+ pointer-events: none;
76
+ }
77
+
78
+ .item-sliding-active-swipe-end .item-options-end .item-option-expandable {
79
+ /* stylelint-disable-next-line property-disallowed-list */
80
+ padding-left: 100%;
81
+ order: 1;
82
+ transition-duration: 0.6s;
83
+ transition-property: padding-left;
84
+ }
85
+ :host-context([dir=rtl]) .item-sliding-active-swipe-end .item-options-end .item-option-expandable {
86
+ order: -1;
87
+ }
88
+
89
+ [dir=rtl] .item-sliding-active-swipe-end .item-options-end .item-option-expandable {
90
+ order: -1;
91
+ }
92
+
93
+ @supports selector(:dir(rtl)) {
94
+ .item-sliding-active-swipe-end .item-options-end .item-option-expandable:dir(rtl) {
95
+ order: -1;
96
+ }
97
+ }
98
+
99
+ .item-sliding-active-swipe-start .item-options-start .item-option-expandable {
100
+ /* stylelint-disable-next-line property-disallowed-list */
101
+ padding-right: 100%;
102
+ order: -1;
103
+ transition-duration: 0.6s;
104
+ transition-property: padding-right;
105
+ }
106
+ :host-context([dir=rtl]) .item-sliding-active-swipe-start .item-options-start .item-option-expandable {
107
+ order: 1;
108
+ }
109
+
110
+ [dir=rtl] .item-sliding-active-swipe-start .item-options-start .item-option-expandable {
111
+ order: 1;
112
+ }
113
+
114
+ @supports selector(:dir(rtl)) {
115
+ .item-sliding-active-swipe-start .item-options-start .item-option-expandable:dir(rtl) {
116
+ order: 1;
117
+ }
118
+ }
119
+
120
+ /**
121
+ * A heuristic that applies CSS to tablet
122
+ * viewports.
123
+ *
124
+ * Usage:
125
+ * @include tablet-viewport() {
126
+ * :host {
127
+ * background-color: green;
128
+ * }
129
+ * }
130
+ */
131
+ /**
132
+ * A heuristic that applies CSS to mobile
133
+ * viewports (i.e. phones, not tablets).
134
+ *
135
+ * Usage:
136
+ * @include mobile-viewport() {
137
+ * :host {
138
+ * background-color: blue;
139
+ * }
140
+ * }
141
+ */
142
+ /**
143
+ * Convert a pixels given value into rem
144
+ *
145
+ * @param pixels - Value in pixels to be converted (i.e. px)
146
+ * @param context (optional) - Baseline value
147
+ */
148
+ /**
149
+ * Convert a font size to a dynamic font size.
150
+ * Fonts that participate in Dynamic Type should use
151
+ * dynamic font sizes.
152
+ * @param size - The initial font size including the unit (i.e. px or pt)
153
+ * @param unit (optional) - The unit to convert to. Use this if you want to
154
+ * convert to a unit other than $baselineUnit.
155
+ */
156
+ /**
157
+ * Convert a font size to a dynamic font size but impose
158
+ * a maximum font size.
159
+ * @param size - The initial font size including the unit (i.e. px or pt)
160
+ * @param maxScale - The maximum scale of the font (i.e. 2.5 for a maximum 250% scale).
161
+ * @param unit (optional) - The unit to convert the initial font size to. Use this if you want to
162
+ * convert to a unit other than $baselineUnit.
163
+ */
164
+ /**
165
+ * Convert a font size to a dynamic font size but impose
166
+ * a minimum font size.
167
+ * @param size - The initial font size including the unit (i.e. px or pt)
168
+ * @param minScale - The minimum scale of the font (i.e. 0.8 for a minimum 80% scale).
169
+ * @param unit (optional) - The unit to convert the initial font size to. Use this if you want to
170
+ * convert to a unit other than $baselineUnit.
171
+ */
172
+ /**
173
+ * Convert a font size to a dynamic font size but impose
174
+ * maximum and minimum font sizes.
175
+ * @param size - The initial font size including the unit (i.e. px or pt)
176
+ * @param minScale - The minimum scale of the font (i.e. 0.8 for a minimum 80% scale).
177
+ * @param maxScale - The maximum scale of the font (i.e. 2.5 for a maximum 250% scale).
178
+ * @param unit (optional) - The unit to convert the initial font size to. Use this if you want to
179
+ * convert to a unit other than $baselineUnit.
180
+ */
181
+ .item-sliding-transition-open .item {
182
+ transition: transform var(--token-transition-time-250, 250ms) var(--token-transition-curve-smooth, cubic-bezier(0.25, 1, 0.5, 1));
183
+ }
184
+
185
+ .item-sliding-transition-snapback .item {
186
+ transition: transform var(--token-transition-time-300, 300ms) var(--token-transition-curve-bounce, cubic-bezier(0.47, 0, 0.23, 1.38));
187
+ }
188
+
189
+ .item-sliding-confirm-item-in .item {
190
+ transition: transform var(--token-transition-time-150, 150ms) var(--token-transition-curve-base, cubic-bezier(0.4, 0, 1, 1));
191
+ }
192
+
193
+ .item-sliding-confirm-item-back .item {
194
+ transition: transform var(--token-transition-time-500, 500ms) var(--token-transition-curve-bounce, cubic-bezier(0.47, 0, 0.23, 1.38));
195
+ }
196
+
197
+ ion-item-option.item-sliding-expandable-width-in {
198
+ transition: width var(--token-transition-time-150, 150ms) var(--token-transition-curve-base, cubic-bezier(0.4, 0, 1, 1));
199
+ }
200
+
201
+ ion-item-option.item-sliding-expandable-width-back {
202
+ transition: width var(--token-transition-time-500, 500ms) var(--token-transition-curve-bounce, cubic-bezier(0.47, 0, 0.23, 1.38));
203
+ }
204
+
205
+ .item-sliding-active-slide .item {
206
+ position: relative;
207
+ opacity: 1;
208
+ z-index: var(--token-z-index-100, 100);
209
+ pointer-events: none;
210
+ will-change: transform;
211
+ }
@@ -9,6 +9,18 @@ import { watchForOptions } from "../../utils/watch-options";
9
9
  import { getIonTheme } from "../../global/ionic-global";
10
10
  const SWIPE_MARGIN = 30;
11
11
  const ELASTIC_FACTOR = 0.55;
12
+ const IONIC_ELASTIC_FACTOR = 0.15;
13
+ const IONIC_SNAP_OPEN_RATIO = 0.4;
14
+ const IONIC_EXPAND_TRIGGER = 40;
15
+ const IONIC_FULL_SWIPE_VELOCITY_THRESHOLD = 400;
16
+ const IONIC_OPEN_VELOCITY_THRESHOLD = 200;
17
+ const IONIC_ACTION_BASE_WIDTH = 64;
18
+ const IONIC_CONFIRM_PAUSE = 300;
19
+ const FULL_SWIPE_TRANSITION_MS = 250;
20
+ const IONIC_EXPAND_RESISTANCE_FACTOR = 0.95;
21
+ /** Expandable, non-disabled option (matches item-option expandable class). */
22
+ const EXPANDABLE_OPTION_SELECTOR = 'ion-item-option.item-option-expandable:not(.item-option-disabled)';
23
+ const ITEM_OPTION_EXPAND_THRESHOLD_CLASS = 'item-option-expand-threshold';
12
24
  let openSlidingItem;
13
25
  /**
14
26
  * @virtualProp {"ios" | "md"} mode - The mode determines the platform behaviors of the component.
@@ -25,12 +37,17 @@ export class ItemSliding {
25
37
  this.optsDirty = true;
26
38
  this.contentEl = null;
27
39
  this.initialContentScrollY = true;
40
+ this.leftExpandableBaseWidth = IONIC_ACTION_BASE_WIDTH;
41
+ this.rightExpandableBaseWidth = IONIC_ACTION_BASE_WIDTH;
28
42
  this.state = 2 /* SlidingState.Disabled */;
29
43
  /**
30
44
  * If `true`, the user cannot interact with the sliding item.
31
45
  */
32
46
  this.disabled = false;
33
47
  }
48
+ isIonicTheme() {
49
+ return getIonTheme(this) === 'ionic';
50
+ }
34
51
  disabledChanged() {
35
52
  if (this.gesture) {
36
53
  this.gesture.enable(!this.disabled);
@@ -230,7 +247,7 @@ export class ItemSliding {
230
247
  if (!this.item) {
231
248
  return resolve();
232
249
  }
233
- this.item.style.transition = `transform ${duration}ms ease-out`;
250
+ this.el.classList.add('item-sliding-full-swipe-transition');
234
251
  this.item.style.transform = `translate3d(${-position}px, 0, 0)`;
235
252
  const id = setTimeout(resolve, duration);
236
253
  signal.addEventListener('abort', () => {
@@ -248,8 +265,8 @@ export class ItemSliding {
248
265
  return maxWidth + SWIPE_MARGIN;
249
266
  }
250
267
  /**
251
- * Animate the item through a full swipe sequence: off-screen → trigger action → return.
252
- * This is used when an expandable option is swiped beyond the threshold.
268
+ * Native (ios/md) full swipe: off-screen → fire swipe → return.
269
+ * Ionic theme uses `animateIonicFullSwipe` instead (see `onEndIonic`).
253
270
  */
254
271
  async animateFullSwipe(direction) {
255
272
  const abortController = new AbortController();
@@ -271,7 +288,7 @@ export class ItemSliding {
271
288
  await this.delay(100, signal);
272
289
  // Animate off-screen while maintaining the expanded state
273
290
  const offScreenDistance = direction === 'end' ? window.innerWidth : -window.innerWidth;
274
- await this.animateToPosition(offScreenDistance, 250, signal);
291
+ await this.animateToPosition(offScreenDistance, FULL_SWIPE_TRANSITION_MS, signal);
275
292
  // Trigger action
276
293
  if (options) {
277
294
  options.fireSwipeEvent();
@@ -279,7 +296,7 @@ export class ItemSliding {
279
296
  // Small delay before returning
280
297
  await this.delay(300, signal);
281
298
  // Return to closed state
282
- await this.animateToPosition(0, 250, signal);
299
+ await this.animateToPosition(0, FULL_SWIPE_TRANSITION_MS, signal);
283
300
  }
284
301
  catch (_a) {
285
302
  // Animation was aborted (e.g. component disconnected). finally handles cleanup.
@@ -287,8 +304,8 @@ export class ItemSliding {
287
304
  finally {
288
305
  this.animationAbortController = undefined;
289
306
  // Reset state
307
+ this.el.classList.remove('item-sliding-full-swipe-transition');
290
308
  if (this.item) {
291
- this.item.style.transition = '';
292
309
  this.item.style.transform = '';
293
310
  }
294
311
  this.openAmount = 0;
@@ -301,6 +318,160 @@ export class ItemSliding {
301
318
  }
302
319
  }
303
320
  }
321
+ queryExpandableOption(options) {
322
+ if (!options) {
323
+ return undefined;
324
+ }
325
+ const expandableOptions = Array.from(options.querySelectorAll(EXPANDABLE_OPTION_SELECTOR));
326
+ if (expandableOptions.length === 0) {
327
+ return undefined;
328
+ }
329
+ if (expandableOptions.length === 1) {
330
+ return expandableOptions[0];
331
+ }
332
+ const isRTL = document.dir === 'rtl';
333
+ const isEndSide = options.classList.contains('item-options-end');
334
+ // Match native edge behavior for multi-expandable configs
335
+ const pickLast = (isEndSide && !isRTL) || (!isEndSide && isRTL);
336
+ return pickLast ? expandableOptions[expandableOptions.length - 1] : expandableOptions[0];
337
+ }
338
+ getExpandableOption(direction) {
339
+ return this.queryExpandableOption(direction === 'end' ? this.rightOptions : this.leftOptions);
340
+ }
341
+ getOpenDirectionFromAmount(openAmount) {
342
+ if (openAmount > 0) {
343
+ return 'end';
344
+ }
345
+ if (openAmount < 0) {
346
+ return 'start';
347
+ }
348
+ return undefined;
349
+ }
350
+ getOptionsWidthForDirection(direction) {
351
+ return direction === 'end' ? this.optsWidthRightSide : this.optsWidthLeftSide;
352
+ }
353
+ getExpandableBaseWidth(direction) {
354
+ return direction === 'end' ? this.rightExpandableBaseWidth : this.leftExpandableBaseWidth;
355
+ }
356
+ setIonicExpandableWidth(direction, width) {
357
+ const expandableOption = this.getExpandableOption(direction);
358
+ if (!expandableOption) {
359
+ return;
360
+ }
361
+ const style = expandableOption.style;
362
+ const baseWidth = this.getExpandableBaseWidth(direction);
363
+ style.width = `${Math.max(baseWidth, width)}px`;
364
+ }
365
+ resetIonicExpandableOptions() {
366
+ [this.leftOptions, this.rightOptions].forEach((options) => {
367
+ if (!options) {
368
+ return;
369
+ }
370
+ options.querySelectorAll(EXPANDABLE_OPTION_SELECTOR).forEach((node) => {
371
+ node.classList.remove(ITEM_OPTION_EXPAND_THRESHOLD_CLASS);
372
+ });
373
+ const expandableOption = this.queryExpandableOption(options);
374
+ if (!expandableOption) {
375
+ return;
376
+ }
377
+ expandableOption.style.width = '';
378
+ expandableOption.classList.remove('item-sliding-expandable-open', 'item-sliding-expandable-snapback', 'item-sliding-expandable-width-in', 'item-sliding-expandable-width-back');
379
+ });
380
+ }
381
+ updateIonicExpandableFromOpenAmount(openAmount, isFinal, previousOpenAmount) {
382
+ var _a;
383
+ if ((this.state & 128 /* SlidingState.AnimatingFullSwipe */) !== 0) {
384
+ return;
385
+ }
386
+ const direction = this.getOpenDirectionFromAmount(openAmount);
387
+ if (direction === undefined) {
388
+ const previousDirection = this.getOpenDirectionFromAmount(previousOpenAmount);
389
+ if (previousDirection === undefined) {
390
+ this.resetIonicExpandableOptions();
391
+ return;
392
+ }
393
+ (_a = this.queryExpandableOption(previousDirection === 'end' ? this.rightOptions : this.leftOptions)) === null || _a === void 0 ? void 0 : _a.classList.remove(ITEM_OPTION_EXPAND_THRESHOLD_CLASS);
394
+ this.setIonicExpandableWidth(previousDirection, this.getExpandableBaseWidth(previousDirection));
395
+ return;
396
+ }
397
+ const baseWidth = this.getExpandableBaseWidth(direction);
398
+ const optionsWidth = this.getOptionsWidthForDirection(direction);
399
+ const extraWidth = Math.max(0, Math.abs(openAmount) - optionsWidth);
400
+ const resistedExtraWidth = isFinal ? extraWidth : extraWidth * IONIC_EXPAND_RESISTANCE_FACTOR;
401
+ const targetWidth = baseWidth + resistedExtraWidth;
402
+ const expandableOption = this.getExpandableOption(direction);
403
+ if (expandableOption) {
404
+ if (!isFinal && extraWidth >= IONIC_EXPAND_TRIGGER) {
405
+ expandableOption.classList.add(ITEM_OPTION_EXPAND_THRESHOLD_CLASS);
406
+ }
407
+ else {
408
+ expandableOption.classList.remove(ITEM_OPTION_EXPAND_THRESHOLD_CLASS);
409
+ }
410
+ }
411
+ this.setIonicExpandableWidth(direction, targetWidth);
412
+ }
413
+ async animateIonicFullSwipe(direction) {
414
+ const abortController = new AbortController();
415
+ this.animationAbortController = abortController;
416
+ const { signal } = abortController;
417
+ const expandableOption = this.getExpandableOption(direction);
418
+ const options = direction === 'end' ? this.rightOptions : this.leftOptions;
419
+ if (this.gesture) {
420
+ this.gesture.enable(false);
421
+ }
422
+ try {
423
+ this.state =
424
+ direction === 'end'
425
+ ? 8 /* SlidingState.End */ | 128 /* SlidingState.AnimatingFullSwipe */
426
+ : 16 /* SlidingState.Start */ | 128 /* SlidingState.AnimatingFullSwipe */;
427
+ if (!this.item) {
428
+ return;
429
+ }
430
+ const itemWidth = this.el.offsetWidth || window.innerWidth;
431
+ const baseWidth = this.getExpandableBaseWidth(direction);
432
+ const expandableTargetWidth = Math.max(baseWidth, itemWidth - 16);
433
+ const offScreenPosition = direction === 'end' ? itemWidth : -itemWidth;
434
+ if (expandableOption) {
435
+ expandableOption.classList.remove('item-sliding-expandable-width-back');
436
+ expandableOption.classList.add('item-sliding-expandable-width-in');
437
+ expandableOption.style.width = `${expandableTargetWidth}px`;
438
+ }
439
+ this.el.classList.remove('item-sliding-confirm-item-back');
440
+ this.el.classList.add('item-sliding-confirm-item-in');
441
+ this.item.style.transform = `translate3d(${-offScreenPosition}px, 0, 0)`;
442
+ await this.delay(150, signal);
443
+ options === null || options === void 0 ? void 0 : options.fireSwipeEvent();
444
+ await this.delay(IONIC_CONFIRM_PAUSE, signal);
445
+ if (expandableOption) {
446
+ expandableOption.classList.remove('item-sliding-expandable-width-in');
447
+ expandableOption.classList.add('item-sliding-expandable-width-back');
448
+ expandableOption.style.width = `${baseWidth}px`;
449
+ }
450
+ this.el.classList.remove('item-sliding-confirm-item-in');
451
+ this.el.classList.add('item-sliding-confirm-item-back');
452
+ this.item.style.transform = 'translate3d(0, 0, 0)';
453
+ await this.delay(500, signal);
454
+ }
455
+ catch (_a) {
456
+ // Animation was aborted. finally handles cleanup.
457
+ }
458
+ finally {
459
+ this.animationAbortController = undefined;
460
+ this.el.classList.remove('item-sliding-confirm-item-in', 'item-sliding-confirm-item-back');
461
+ if (this.item) {
462
+ this.item.style.transform = '';
463
+ }
464
+ this.resetIonicExpandableOptions();
465
+ this.openAmount = 0;
466
+ this.state = 2 /* SlidingState.Disabled */;
467
+ if (openSlidingItem === this.el) {
468
+ openSlidingItem = undefined;
469
+ }
470
+ if (this.gesture) {
471
+ this.gesture.enable(!this.disabled);
472
+ }
473
+ }
474
+ }
304
475
  async updateOptions() {
305
476
  var _a;
306
477
  const options = this.el.querySelectorAll('ion-item-options');
@@ -368,7 +539,12 @@ export class ItemSliding {
368
539
  }
369
540
  this.initialOpenAmount = this.openAmount;
370
541
  if (this.item) {
371
- this.item.style.transition = 'none';
542
+ if (this.isIonicTheme()) {
543
+ this.el.classList.remove('item-sliding-transition-open', 'item-sliding-transition-snapback');
544
+ }
545
+ else {
546
+ this.el.classList.add('item-sliding-dragging');
547
+ }
372
548
  }
373
549
  }
374
550
  onMove(gesture) {
@@ -391,22 +567,46 @@ export class ItemSliding {
391
567
  printIonWarning('[ion-item-sliding] - invalid ItemSideFlags value', this.sides);
392
568
  break;
393
569
  }
394
- let optsWidth;
395
- if (openAmount > this.optsWidthRightSide) {
396
- optsWidth = this.optsWidthRightSide;
397
- openAmount = optsWidth + (openAmount - optsWidth) * ELASTIC_FACTOR;
570
+ if (this.isIonicTheme()) {
571
+ if (openAmount > this.optsWidthRightSide) {
572
+ const overDrag = openAmount - this.optsWidthRightSide;
573
+ openAmount = this.optsWidthRightSide + overDrag * IONIC_ELASTIC_FACTOR;
574
+ }
575
+ else if (openAmount < -this.optsWidthLeftSide) {
576
+ const overDrag = openAmount + this.optsWidthLeftSide;
577
+ openAmount = -this.optsWidthLeftSide + overDrag * IONIC_ELASTIC_FACTOR;
578
+ }
398
579
  }
399
- else if (openAmount < -this.optsWidthLeftSide) {
400
- optsWidth = -this.optsWidthLeftSide;
401
- openAmount = optsWidth + (openAmount - optsWidth) * ELASTIC_FACTOR;
580
+ else {
581
+ let optsWidth;
582
+ if (openAmount > this.optsWidthRightSide) {
583
+ optsWidth = this.optsWidthRightSide;
584
+ openAmount = optsWidth + (openAmount - optsWidth) * ELASTIC_FACTOR;
585
+ }
586
+ else if (openAmount < -this.optsWidthLeftSide) {
587
+ optsWidth = -this.optsWidthLeftSide;
588
+ openAmount = optsWidth + (openAmount - optsWidth) * ELASTIC_FACTOR;
589
+ }
402
590
  }
403
591
  this.setOpenAmount(openAmount, false);
404
592
  }
405
593
  onEnd(gesture) {
594
+ this.el.classList.remove('item-sliding-dragging');
595
+ this.restoreContentScrollAfterSlide();
596
+ if (this.isIonicTheme()) {
597
+ this.onEndIonic(gesture);
598
+ }
599
+ else {
600
+ this.onEndNative(gesture);
601
+ }
602
+ }
603
+ restoreContentScrollAfterSlide() {
406
604
  const { contentEl, initialContentScrollY } = this;
407
605
  if (contentEl) {
408
606
  resetContentScrollY(contentEl, initialContentScrollY);
409
607
  }
608
+ }
609
+ onEndNative(gesture) {
410
610
  // Check for full swipe conditions with expandable options
411
611
  const rawSwipeDistance = Math.abs(gesture.deltaX);
412
612
  const direction = gesture.deltaX < 0 ? 'end' : 'start';
@@ -443,17 +643,64 @@ export class ItemSliding {
443
643
  this.leftOptions.fireSwipeEvent();
444
644
  }
445
645
  }
646
+ onEndIonic(gesture) {
647
+ const velocity = gesture.velocityX;
648
+ const velocityX = velocity * 1000;
649
+ const activeDirection = this.getOpenDirectionFromAmount(this.openAmount);
650
+ if (activeDirection === undefined) {
651
+ this.setOpenAmount(0, true);
652
+ return;
653
+ }
654
+ const optionsWidth = this.getOptionsWidthForDirection(activeDirection);
655
+ const extraWidth = Math.max(0, Math.abs(this.openAmount) - optionsWidth);
656
+ const hasExpandable = this.hasExpandableOptions(activeDirection === 'end' ? this.rightOptions : this.leftOptions);
657
+ const closeDirection = activeDirection === 'end'
658
+ ? velocityX > IONIC_FULL_SWIPE_VELOCITY_THRESHOLD
659
+ : velocityX < -IONIC_FULL_SWIPE_VELOCITY_THRESHOLD;
660
+ if (closeDirection) {
661
+ this.setOpenAmount(0, true);
662
+ return;
663
+ }
664
+ if (hasExpandable &&
665
+ (extraWidth >= IONIC_EXPAND_TRIGGER ||
666
+ (extraWidth > 0 && Math.abs(velocityX) > IONIC_FULL_SWIPE_VELOCITY_THRESHOLD))) {
667
+ this.animateIonicFullSwipe(activeDirection).catch(() => {
668
+ if (this.gesture) {
669
+ this.gesture.enable(!this.disabled);
670
+ }
671
+ });
672
+ return;
673
+ }
674
+ const flickOpen = activeDirection === 'end'
675
+ ? velocityX < -IONIC_OPEN_VELOCITY_THRESHOLD
676
+ : velocityX > IONIC_OPEN_VELOCITY_THRESHOLD;
677
+ const fullOpen = activeDirection === 'end' ? this.optsWidthRightSide : -this.optsWidthLeftSide;
678
+ const openThreshold = optionsWidth * IONIC_SNAP_OPEN_RATIO;
679
+ const shouldSnapOpen = flickOpen || Math.abs(this.openAmount) > openThreshold;
680
+ const restingPoint = shouldSnapOpen ? fullOpen : 0;
681
+ this.setOpenAmount(restingPoint, true);
682
+ }
446
683
  calculateOptsWidth() {
447
684
  this.optsWidthRightSide = 0;
448
685
  if (this.rightOptions) {
449
686
  this.rightOptions.style.display = 'flex';
450
687
  this.optsWidthRightSide = this.rightOptions.offsetWidth;
688
+ const rightExpandable = this.queryExpandableOption(this.rightOptions);
689
+ if (rightExpandable) {
690
+ rightExpandable.style.width = '';
691
+ this.rightExpandableBaseWidth = Math.max(IONIC_ACTION_BASE_WIDTH, rightExpandable.getBoundingClientRect().width);
692
+ }
451
693
  this.rightOptions.style.display = '';
452
694
  }
453
695
  this.optsWidthLeftSide = 0;
454
696
  if (this.leftOptions) {
455
697
  this.leftOptions.style.display = 'flex';
456
698
  this.optsWidthLeftSide = this.leftOptions.offsetWidth;
699
+ const leftExpandable = this.queryExpandableOption(this.leftOptions);
700
+ if (leftExpandable) {
701
+ leftExpandable.style.width = '';
702
+ this.leftExpandableBaseWidth = Math.max(IONIC_ACTION_BASE_WIDTH, leftExpandable.getBoundingClientRect().width);
703
+ }
457
704
  this.leftOptions.style.display = '';
458
705
  }
459
706
  this.optsDirty = false;
@@ -468,35 +715,30 @@ export class ItemSliding {
468
715
  }
469
716
  const { el } = this;
470
717
  const style = this.item.style;
718
+ const previousOpenAmount = this.openAmount;
471
719
  this.openAmount = openAmount;
472
- if (isFinal) {
473
- style.transition = '';
720
+ if (this.isIonicTheme()) {
721
+ this.updateIonicExpandableFromOpenAmount(openAmount, isFinal, previousOpenAmount);
722
+ }
723
+ if (this.isIonicTheme() && isFinal) {
724
+ const closing = Math.abs(openAmount) < Math.abs(previousOpenAmount);
725
+ if (closing) {
726
+ this.el.classList.add('item-sliding-transition-snapback');
727
+ }
728
+ else {
729
+ this.el.classList.add('item-sliding-transition-open');
730
+ }
474
731
  }
475
732
  if (openAmount > 0) {
476
- this.state =
477
- openAmount >= this.optsWidthRightSide + SWIPE_MARGIN
478
- ? 8 /* SlidingState.End */ | 32 /* SlidingState.SwipeEnd */
479
- : 8 /* SlidingState.End */;
733
+ const fullSwipe = !this.isIonicTheme() && openAmount >= this.optsWidthRightSide + SWIPE_MARGIN;
734
+ this.state = fullSwipe ? 8 /* SlidingState.End */ | 32 /* SlidingState.SwipeEnd */ : 8 /* SlidingState.End */;
480
735
  }
481
736
  else if (openAmount < 0) {
482
- this.state =
483
- openAmount <= -this.optsWidthLeftSide - SWIPE_MARGIN
484
- ? 16 /* SlidingState.Start */ | 64 /* SlidingState.SwipeStart */
485
- : 16 /* SlidingState.Start */;
737
+ const fullSwipe = !this.isIonicTheme() && openAmount <= -this.optsWidthLeftSide - SWIPE_MARGIN;
738
+ this.state = fullSwipe ? 16 /* SlidingState.Start */ | 64 /* SlidingState.SwipeStart */ : 16 /* SlidingState.Start */;
486
739
  }
487
740
  else {
488
- /**
489
- * The sliding options should not be
490
- * clickable while the item is closing.
491
- */
492
741
  el.classList.add('item-sliding-closing');
493
- /**
494
- * Item sliding cannot be interrupted
495
- * while closing the item. If it did,
496
- * it would allow the item to get into an
497
- * inconsistent state where multiple
498
- * items are then open at the same time.
499
- */
500
742
  if (this.gesture) {
501
743
  this.gesture.enable(false);
502
744
  }
@@ -531,7 +773,7 @@ export class ItemSliding {
531
773
  }
532
774
  render() {
533
775
  const theme = getIonTheme(this);
534
- return (h(Host, { key: 'c945f30d9f7deb90d22064d4059e2b08f35614be', class: {
776
+ return (h(Host, { key: 'ca0730d5ee00f245b6a139d9fb53fcc8c529a8c6', class: {
535
777
  [theme]: true,
536
778
  'item-sliding-active-slide': this.state !== 2 /* SlidingState.Disabled */,
537
779
  'item-sliding-active-options-end': (this.state & 8 /* SlidingState.End */) !== 0,
@@ -543,12 +785,16 @@ export class ItemSliding {
543
785
  static get is() { return "ion-item-sliding"; }
544
786
  static get originalStyleUrls() {
545
787
  return {
546
- "$": ["item-sliding.scss"]
788
+ "ios": ["item-sliding.native.scss"],
789
+ "md": ["item-sliding.native.scss"],
790
+ "ionic": ["item-sliding.ionic.scss"]
547
791
  };
548
792
  }
549
793
  static get styleUrls() {
550
794
  return {
551
- "$": ["item-sliding.css"]
795
+ "ios": ["item-sliding.native.css"],
796
+ "md": ["item-sliding.native.css"],
797
+ "ionic": ["item-sliding.ionic.css"]
552
798
  };
553
799
  }
554
800
  static get properties() {