UNPKG

29.9 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, '__esModule', { value: true });
4
5const index = require('./index-a0a08b2a.js');
6const ionicGlobal = require('./ionic-global-06f21c1a.js');
7const theme = require('./theme-30b7a575.js');
8const helpers = require('./helpers-d381ec4d.js');
9
10const itemOptionIosCss = ":host{--background:var(--ion-color-primary, #3880ff);--color:var(--ion-color-primary-contrast, #fff);background:var(--background);color:var(--color);font-family:var(--ion-font-family, inherit)}:host(.in-list.item-options-end:last-child){padding-right:calc(.7em + var(--ion-safe-area-right))}@supports ((-webkit-margin-start: 0) or (margin-inline-start: 0)) or (-webkit-margin-start: 0){:host(.in-list.item-options-end:last-child){padding-right:unset;-webkit-padding-end:calc(.7em + var(--ion-safe-area-right));padding-inline-end:calc(.7em + var(--ion-safe-area-right))}}:host(.in-list.item-options-start:first-child){padding-left:calc(.7em + var(--ion-safe-area-left))}@supports ((-webkit-margin-start: 0) or (margin-inline-start: 0)) or (-webkit-margin-start: 0){:host(.in-list.item-options-start:first-child){padding-left:unset;-webkit-padding-start:calc(.7em + var(--ion-safe-area-left));padding-inline-start:calc(.7em + var(--ion-safe-area-left))}}:host(.ion-color){background:var(--ion-color-base);color:var(--ion-color-contrast)}.button-native{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;letter-spacing:inherit;text-decoration:inherit;text-indent:inherit;text-overflow:inherit;text-transform:inherit;text-align:inherit;white-space:inherit;color:inherit;padding-left:0.7em;padding-right:0.7em;padding-top:0;padding-bottom:0;display:inline-block;position:relative;width:100%;height:100%;border:0;outline:none;background:transparent;cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;-webkit-box-sizing:border-box;box-sizing:border-box}@supports ((-webkit-margin-start: 0) or (margin-inline-start: 0)) or (-webkit-margin-start: 0){.button-native{padding-left:unset;padding-right:unset;-webkit-padding-start:0.7em;padding-inline-start:0.7em;-webkit-padding-end:0.7em;padding-inline-end:0.7em}}.button-inner{display:-ms-flexbox;display:flex;-ms-flex-flow:column nowrap;flex-flow:column nowrap;-ms-flex-negative:0;flex-shrink:0;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;width:100%;height:100%}.horizontal-wrapper{display:-ms-flexbox;display:flex;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-negative:0;flex-shrink:0;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;width:100%}::slotted(*){-ms-flex-negative:0;flex-shrink:0}::slotted([slot=start]){margin-left:0;margin-right:5px;margin-top:0;margin-bottom:0}@supports ((-webkit-margin-start: 0) or (margin-inline-start: 0)) or (-webkit-margin-start: 0){::slotted([slot=start]){margin-left:unset;margin-right:unset;-webkit-margin-start:0;margin-inline-start:0;-webkit-margin-end:5px;margin-inline-end:5px}}::slotted([slot=end]){margin-left:5px;margin-right:0;margin-top:0;margin-bottom:0}@supports ((-webkit-margin-start: 0) or (margin-inline-start: 0)) or (-webkit-margin-start: 0){::slotted([slot=end]){margin-left:unset;margin-right:unset;-webkit-margin-start:5px;margin-inline-start:5px;-webkit-margin-end:0;margin-inline-end:0}}::slotted([slot=icon-only]){padding-left:0;padding-right:0;padding-top:0;padding-bottom:0;margin-left:10px;margin-right:10px;margin-top:0;margin-bottom:0;min-width:0.9em;font-size:1.8em}@supports ((-webkit-margin-start: 0) or (margin-inline-start: 0)) or (-webkit-margin-start: 0){::slotted([slot=icon-only]){margin-left:unset;margin-right:unset;-webkit-margin-start:10px;margin-inline-start:10px;-webkit-margin-end:10px;margin-inline-end:10px}}:host(.item-option-expandable){-ms-flex-negative:0;flex-shrink:0;-webkit-transition-duration:0;transition-duration:0;-webkit-transition-property:none;transition-property:none;-webkit-transition-timing-function:cubic-bezier(0.65, 0.05, 0.36, 1);transition-timing-function:cubic-bezier(0.65, 0.05, 0.36, 1)}:host(.item-option-disabled){pointer-events:none}:host(.item-option-disabled) .button-native{cursor:default;opacity:0.5;pointer-events:none}:host{font-size:16px}:host(.ion-activated){background:var(--ion-color-primary-shade, #3171e0)}:host(.ion-color.ion-activated){background:var(--ion-color-shade)}";
11
12const itemOptionMdCss = ":host{--background:var(--ion-color-primary, #3880ff);--color:var(--ion-color-primary-contrast, #fff);background:var(--background);color:var(--color);font-family:var(--ion-font-family, inherit)}:host(.in-list.item-options-end:last-child){padding-right:calc(.7em + var(--ion-safe-area-right))}@supports ((-webkit-margin-start: 0) or (margin-inline-start: 0)) or (-webkit-margin-start: 0){:host(.in-list.item-options-end:last-child){padding-right:unset;-webkit-padding-end:calc(.7em + var(--ion-safe-area-right));padding-inline-end:calc(.7em + var(--ion-safe-area-right))}}:host(.in-list.item-options-start:first-child){padding-left:calc(.7em + var(--ion-safe-area-left))}@supports ((-webkit-margin-start: 0) or (margin-inline-start: 0)) or (-webkit-margin-start: 0){:host(.in-list.item-options-start:first-child){padding-left:unset;-webkit-padding-start:calc(.7em + var(--ion-safe-area-left));padding-inline-start:calc(.7em + var(--ion-safe-area-left))}}:host(.ion-color){background:var(--ion-color-base);color:var(--ion-color-contrast)}.button-native{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;letter-spacing:inherit;text-decoration:inherit;text-indent:inherit;text-overflow:inherit;text-transform:inherit;text-align:inherit;white-space:inherit;color:inherit;padding-left:0.7em;padding-right:0.7em;padding-top:0;padding-bottom:0;display:inline-block;position:relative;width:100%;height:100%;border:0;outline:none;background:transparent;cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;-webkit-box-sizing:border-box;box-sizing:border-box}@supports ((-webkit-margin-start: 0) or (margin-inline-start: 0)) or (-webkit-margin-start: 0){.button-native{padding-left:unset;padding-right:unset;-webkit-padding-start:0.7em;padding-inline-start:0.7em;-webkit-padding-end:0.7em;padding-inline-end:0.7em}}.button-inner{display:-ms-flexbox;display:flex;-ms-flex-flow:column nowrap;flex-flow:column nowrap;-ms-flex-negative:0;flex-shrink:0;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;width:100%;height:100%}.horizontal-wrapper{display:-ms-flexbox;display:flex;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-negative:0;flex-shrink:0;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;width:100%}::slotted(*){-ms-flex-negative:0;flex-shrink:0}::slotted([slot=start]){margin-left:0;margin-right:5px;margin-top:0;margin-bottom:0}@supports ((-webkit-margin-start: 0) or (margin-inline-start: 0)) or (-webkit-margin-start: 0){::slotted([slot=start]){margin-left:unset;margin-right:unset;-webkit-margin-start:0;margin-inline-start:0;-webkit-margin-end:5px;margin-inline-end:5px}}::slotted([slot=end]){margin-left:5px;margin-right:0;margin-top:0;margin-bottom:0}@supports ((-webkit-margin-start: 0) or (margin-inline-start: 0)) or (-webkit-margin-start: 0){::slotted([slot=end]){margin-left:unset;margin-right:unset;-webkit-margin-start:5px;margin-inline-start:5px;-webkit-margin-end:0;margin-inline-end:0}}::slotted([slot=icon-only]){padding-left:0;padding-right:0;padding-top:0;padding-bottom:0;margin-left:10px;margin-right:10px;margin-top:0;margin-bottom:0;min-width:0.9em;font-size:1.8em}@supports ((-webkit-margin-start: 0) or (margin-inline-start: 0)) or (-webkit-margin-start: 0){::slotted([slot=icon-only]){margin-left:unset;margin-right:unset;-webkit-margin-start:10px;margin-inline-start:10px;-webkit-margin-end:10px;margin-inline-end:10px}}:host(.item-option-expandable){-ms-flex-negative:0;flex-shrink:0;-webkit-transition-duration:0;transition-duration:0;-webkit-transition-property:none;transition-property:none;-webkit-transition-timing-function:cubic-bezier(0.65, 0.05, 0.36, 1);transition-timing-function:cubic-bezier(0.65, 0.05, 0.36, 1)}:host(.item-option-disabled){pointer-events:none}:host(.item-option-disabled) .button-native{cursor:default;opacity:0.5;pointer-events:none}:host{font-size:14px;font-weight:500;text-transform:uppercase}";
13
14const ItemOption = class {
15 constructor(hostRef) {
16 index.registerInstance(this, hostRef);
17 /**
18 * If `true`, the user cannot interact with the item option.
19 */
20 this.disabled = false;
21 /**
22 * If `true`, the option will expand to take up the available width and cover any other options.
23 */
24 this.expandable = false;
25 /**
26 * The type of the button.
27 */
28 this.type = 'button';
29 this.onClick = (ev) => {
30 const el = ev.target.closest('ion-item-option');
31 if (el) {
32 ev.preventDefault();
33 }
34 };
35 }
36 render() {
37 const { disabled, expandable, href } = this;
38 const TagType = href === undefined ? 'button' : 'a';
39 const mode = ionicGlobal.getIonMode(this);
40 const attrs = (TagType === 'button')
41 ? { type: this.type }
42 : {
43 download: this.download,
44 href: this.href,
45 target: this.target
46 };
47 return (index.h(index.Host, { onClick: this.onClick, class: theme.createColorClasses(this.color, {
48 [mode]: true,
49 'item-option-disabled': disabled,
50 'item-option-expandable': expandable,
51 'ion-activatable': true
52 }) }, index.h(TagType, Object.assign({}, attrs, { class: "button-native", part: "native", disabled: disabled }), index.h("span", { class: "button-inner" }, index.h("slot", { name: "top" }), index.h("div", { class: "horizontal-wrapper" }, index.h("slot", { name: "start" }), index.h("slot", { name: "icon-only" }), index.h("slot", null), index.h("slot", { name: "end" })), index.h("slot", { name: "bottom" })), mode === 'md' && index.h("ion-ripple-effect", null))));
53 }
54 get el() { return index.getElement(this); }
55};
56ItemOption.style = {
57 ios: itemOptionIosCss,
58 md: itemOptionMdCss
59};
60
61const itemOptionsIosCss = "ion-item-options{top:0;right:0;-ms-flex-pack:end;justify-content:flex-end;display:none;position:absolute;height:100%;font-size:14px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;z-index:1}[dir=rtl] ion-item-options,:host-context([dir=rtl]) ion-item-options{-ms-flex-pack:start;justify-content:flex-start}[dir=rtl] ion-item-options:not(.item-options-end),:host-context([dir=rtl]) ion-item-options:not(.item-options-end){right:auto;left:0;-ms-flex-pack:end;justify-content:flex-end}.item-options-start{right:auto;left:0;-ms-flex-pack:start;justify-content:flex-start}[dir=rtl] .item-options-start,:host-context([dir=rtl]) .item-options-start{-ms-flex-pack:end;justify-content:flex-end}.item-options-start ion-item-option:first-child{padding-right:var(--ion-safe-area-left)}@supports ((-webkit-margin-start: 0) or (margin-inline-start: 0)) or (-webkit-margin-start: 0){.item-options-start ion-item-option:first-child{padding-right:unset;-webkit-padding-end:var(--ion-safe-area-left);padding-inline-end:var(--ion-safe-area-left)}}.item-options-end ion-item-option:last-child{padding-right:var(--ion-safe-area-right)}@supports ((-webkit-margin-start: 0) or (margin-inline-start: 0)) or (-webkit-margin-start: 0){.item-options-end ion-item-option:last-child{padding-right:unset;-webkit-padding-end:var(--ion-safe-area-right);padding-inline-end:var(--ion-safe-area-right)}}[dir=rtl] .item-sliding-active-slide.item-sliding-active-options-start ion-item-options:not(.item-options-end),:host-context([dir=rtl]) .item-sliding-active-slide.item-sliding-active-options-start ion-item-options:not(.item-options-end){width:100%;visibility:visible}.item-sliding-active-slide ion-item-options{display:-ms-flexbox;display:flex;visibility:hidden}.item-sliding-active-slide.item-sliding-active-options-start .item-options-start,.item-sliding-active-slide.item-sliding-active-options-end ion-item-options:not(.item-options-start){width:100%;visibility:visible}.item-options-ios{border-bottom-width:0;border-bottom-style:solid;border-bottom-color:var(--ion-item-border-color, var(--ion-border-color, var(--ion-color-step-250, #c8c7cc)))}.item-options-ios.item-options-end{border-bottom-width:0.55px}.list-ios-lines-none .item-options-ios{border-bottom-width:0}.list-ios-lines-full .item-options-ios,.list-ios-lines-inset .item-options-ios.item-options-end{border-bottom-width:0.55px}";
62
63const itemOptionsMdCss = "ion-item-options{top:0;right:0;-ms-flex-pack:end;justify-content:flex-end;display:none;position:absolute;height:100%;font-size:14px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;z-index:1}[dir=rtl] ion-item-options,:host-context([dir=rtl]) ion-item-options{-ms-flex-pack:start;justify-content:flex-start}[dir=rtl] ion-item-options:not(.item-options-end),:host-context([dir=rtl]) ion-item-options:not(.item-options-end){right:auto;left:0;-ms-flex-pack:end;justify-content:flex-end}.item-options-start{right:auto;left:0;-ms-flex-pack:start;justify-content:flex-start}[dir=rtl] .item-options-start,:host-context([dir=rtl]) .item-options-start{-ms-flex-pack:end;justify-content:flex-end}.item-options-start ion-item-option:first-child{padding-right:var(--ion-safe-area-left)}@supports ((-webkit-margin-start: 0) or (margin-inline-start: 0)) or (-webkit-margin-start: 0){.item-options-start ion-item-option:first-child{padding-right:unset;-webkit-padding-end:var(--ion-safe-area-left);padding-inline-end:var(--ion-safe-area-left)}}.item-options-end ion-item-option:last-child{padding-right:var(--ion-safe-area-right)}@supports ((-webkit-margin-start: 0) or (margin-inline-start: 0)) or (-webkit-margin-start: 0){.item-options-end ion-item-option:last-child{padding-right:unset;-webkit-padding-end:var(--ion-safe-area-right);padding-inline-end:var(--ion-safe-area-right)}}[dir=rtl] .item-sliding-active-slide.item-sliding-active-options-start ion-item-options:not(.item-options-end),:host-context([dir=rtl]) .item-sliding-active-slide.item-sliding-active-options-start ion-item-options:not(.item-options-end){width:100%;visibility:visible}.item-sliding-active-slide ion-item-options{display:-ms-flexbox;display:flex;visibility:hidden}.item-sliding-active-slide.item-sliding-active-options-start .item-options-start,.item-sliding-active-slide.item-sliding-active-options-end ion-item-options:not(.item-options-start){width:100%;visibility:visible}.item-options-md{border-bottom-width:0;border-bottom-style:solid;border-bottom-color:var(--ion-item-border-color, var(--ion-border-color, var(--ion-color-step-150, rgba(0, 0, 0, 0.13))))}.list-md-lines-none .item-options-md{border-bottom-width:0}.list-md-lines-full .item-options-md,.list-md-lines-inset .item-options-md.item-options-end{border-bottom-width:1px}";
64
65const ItemOptions = class {
66 constructor(hostRef) {
67 index.registerInstance(this, hostRef);
68 this.ionSwipe = index.createEvent(this, "ionSwipe", 7);
69 /**
70 * The side the option button should be on. Possible values: `"start"` and `"end"`. If you have multiple `ion-item-options`, a side must be provided for each.
71 *
72 */
73 this.side = 'end';
74 }
75 /** @internal */
76 async fireSwipeEvent() {
77 this.ionSwipe.emit({
78 side: this.side
79 });
80 }
81 render() {
82 const mode = ionicGlobal.getIonMode(this);
83 const isEnd = helpers.isEndSide(this.side);
84 return (index.h(index.Host, { class: {
85 [mode]: true,
86 // Used internally for styling
87 [`item-options-${mode}`]: true,
88 'item-options-start': !isEnd,
89 'item-options-end': isEnd
90 } }));
91 }
92 get el() { return index.getElement(this); }
93};
94ItemOptions.style = {
95 ios: itemOptionsIosCss,
96 md: itemOptionsMdCss
97};
98
99const itemSlidingCss = "ion-item-sliding{display:block;position:relative;width:100%;overflow:hidden;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}ion-item-sliding .item{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.item-sliding-active-slide .item{position:relative;-webkit-transition:-webkit-transform 500ms cubic-bezier(0.36, 0.66, 0.04, 1);transition:-webkit-transform 500ms cubic-bezier(0.36, 0.66, 0.04, 1);transition:transform 500ms cubic-bezier(0.36, 0.66, 0.04, 1);transition:transform 500ms cubic-bezier(0.36, 0.66, 0.04, 1), -webkit-transform 500ms cubic-bezier(0.36, 0.66, 0.04, 1);opacity:1;z-index:2;pointer-events:none;will-change:transform}.item-sliding-active-swipe-end .item-options-end .item-option-expandable{padding-left:100%;-ms-flex-order:1;order:1;-webkit-transition-duration:0.6s;transition-duration:0.6s;-webkit-transition-property:padding-left;transition-property:padding-left}[dir=rtl] .item-sliding-active-swipe-end .item-options-end .item-option-expandable,:host-context([dir=rtl]) .item-sliding-active-swipe-end .item-options-end .item-option-expandable{-ms-flex-order:-1;order:-1}.item-sliding-active-swipe-start .item-options-start .item-option-expandable{padding-right:100%;-ms-flex-order:-1;order:-1;-webkit-transition-duration:0.6s;transition-duration:0.6s;-webkit-transition-property:padding-right;transition-property:padding-right}[dir=rtl] .item-sliding-active-swipe-start .item-options-start .item-option-expandable,:host-context([dir=rtl]) .item-sliding-active-swipe-start .item-options-start .item-option-expandable{-ms-flex-order:1;order:1}";
100
101const SWIPE_MARGIN = 30;
102const ELASTIC_FACTOR = 0.55;
103let openSlidingItem;
104const ItemSliding = class {
105 constructor(hostRef) {
106 index.registerInstance(this, hostRef);
107 this.ionDrag = index.createEvent(this, "ionDrag", 7);
108 this.item = null;
109 this.openAmount = 0;
110 this.initialOpenAmount = 0;
111 this.optsWidthRightSide = 0;
112 this.optsWidthLeftSide = 0;
113 this.sides = 0 /* None */;
114 this.optsDirty = true;
115 this.closestContent = null;
116 this.initialContentScrollY = true;
117 this.state = 2 /* Disabled */;
118 /**
119 * If `true`, the user cannot interact with the sliding item.
120 */
121 this.disabled = false;
122 }
123 disabledChanged() {
124 if (this.gesture) {
125 this.gesture.enable(!this.disabled);
126 }
127 }
128 async connectedCallback() {
129 this.item = this.el.querySelector('ion-item');
130 this.closestContent = this.el.closest('ion-content');
131 await this.updateOptions();
132 this.gesture = (await Promise.resolve().then(function () { return require('./index-a1dd5c93.js'); })).createGesture({
133 el: this.el,
134 gestureName: 'item-swipe',
135 gesturePriority: 100,
136 threshold: 5,
137 canStart: ev => this.canStart(ev),
138 onStart: () => this.onStart(),
139 onMove: ev => this.onMove(ev),
140 onEnd: ev => this.onEnd(ev),
141 });
142 this.disabledChanged();
143 }
144 disconnectedCallback() {
145 if (this.gesture) {
146 this.gesture.destroy();
147 this.gesture = undefined;
148 }
149 this.item = null;
150 this.leftOptions = this.rightOptions = undefined;
151 if (openSlidingItem === this.el) {
152 openSlidingItem = undefined;
153 }
154 }
155 /**
156 * Get the amount the item is open in pixels.
157 */
158 getOpenAmount() {
159 return Promise.resolve(this.openAmount);
160 }
161 /**
162 * Get the ratio of the open amount of the item compared to the width of the options.
163 * If the number returned is positive, then the options on the right side are open.
164 * If the number returned is negative, then the options on the left side are open.
165 * If the absolute value of the number is greater than 1, the item is open more than
166 * the width of the options.
167 */
168 getSlidingRatio() {
169 return Promise.resolve(this.getSlidingRatioSync());
170 }
171 /**
172 * Open the sliding item.
173 *
174 * @param side The side of the options to open. If a side is not provided, it will open the first set of options it finds within the item.
175 */
176 async open(side) {
177 if (this.item === null) {
178 return;
179 }
180 const optionsToOpen = this.getOptions(side);
181 if (!optionsToOpen) {
182 return;
183 }
184 /**
185 * If side is not set, we need to infer the side
186 * so we know which direction to move the options
187 */
188 if (side === undefined) {
189 side = (optionsToOpen === this.leftOptions) ? 'start' : 'end';
190 }
191 // In RTL we want to switch the sides
192 side = helpers.isEndSide(side) ? 'end' : 'start';
193 const isStartOpen = this.openAmount < 0;
194 const isEndOpen = this.openAmount > 0;
195 /**
196 * If a side is open and a user tries to
197 * re-open the same side, we should not do anything
198 */
199 if (isStartOpen && optionsToOpen === this.leftOptions) {
200 return;
201 }
202 if (isEndOpen && optionsToOpen === this.rightOptions) {
203 return;
204 }
205 this.closeOpened();
206 this.state = 4 /* Enabled */;
207 requestAnimationFrame(() => {
208 this.calculateOptsWidth();
209 const width = (side === 'end') ? this.optsWidthRightSide : -this.optsWidthLeftSide;
210 openSlidingItem = this.el;
211 this.setOpenAmount(width, false);
212 this.state = (side === 'end') ? 8 /* End */ : 16 /* Start */;
213 });
214 }
215 /**
216 * Close the sliding item. Items can also be closed from the [List](../list).
217 */
218 async close() {
219 this.setOpenAmount(0, true);
220 }
221 /**
222 * Close all of the sliding items in the list. Items can also be closed from the [List](../list).
223 */
224 async closeOpened() {
225 if (openSlidingItem !== undefined) {
226 openSlidingItem.close();
227 openSlidingItem = undefined;
228 return true;
229 }
230 return false;
231 }
232 /**
233 * Given an optional side, return the ion-item-options element.
234 *
235 * @param side This side of the options to get. If a side is not provided it will
236 * return the first one available.
237 */
238 getOptions(side) {
239 if (side === undefined) {
240 return this.leftOptions || this.rightOptions;
241 }
242 else if (side === 'start') {
243 return this.leftOptions;
244 }
245 else {
246 return this.rightOptions;
247 }
248 }
249 async updateOptions() {
250 const options = this.el.querySelectorAll('ion-item-options');
251 let sides = 0;
252 // Reset left and right options in case they were removed
253 this.leftOptions = this.rightOptions = undefined;
254 for (let i = 0; i < options.length; i++) {
255 const item = options.item(i);
256 /**
257 * We cannot use the componentOnReady helper
258 * util here since we need to wait for all of these items
259 * to be ready before we set `this.sides` and `this.optsDirty`.
260 */
261 const option = (item.componentOnReady !== undefined) ? await item.componentOnReady() : item;
262 const side = helpers.isEndSide(option.side) ? 'end' : 'start';
263 if (side === 'start') {
264 this.leftOptions = option;
265 sides |= 1 /* Start */;
266 }
267 else {
268 this.rightOptions = option;
269 sides |= 2 /* End */;
270 }
271 }
272 this.optsDirty = true;
273 this.sides = sides;
274 }
275 canStart(gesture) {
276 /**
277 * If very close to start of the screen
278 * do not open left side so swipe to go
279 * back will still work.
280 */
281 const rtl = document.dir === 'rtl';
282 const atEdge = (rtl) ? (window.innerWidth - gesture.startX) < 15 : gesture.startX < 15;
283 if (atEdge) {
284 return false;
285 }
286 const selected = openSlidingItem;
287 if (selected && selected !== this.el) {
288 this.closeOpened();
289 }
290 return !!(this.rightOptions || this.leftOptions);
291 }
292 disableContentScrollY() {
293 if (this.closestContent === null) {
294 return;
295 }
296 this.initialContentScrollY = this.closestContent.scrollY;
297 this.closestContent.scrollY = false;
298 }
299 restoreContentScrollY() {
300 if (this.closestContent === null) {
301 return;
302 }
303 this.closestContent.scrollY = this.initialContentScrollY;
304 }
305 onStart() {
306 // Prevent scrolling during gesture
307 this.disableContentScrollY();
308 openSlidingItem = this.el;
309 if (this.tmr !== undefined) {
310 clearTimeout(this.tmr);
311 this.tmr = undefined;
312 }
313 if (this.openAmount === 0) {
314 this.optsDirty = true;
315 this.state = 4 /* Enabled */;
316 }
317 this.initialOpenAmount = this.openAmount;
318 if (this.item) {
319 this.item.style.transition = 'none';
320 }
321 }
322 onMove(gesture) {
323 if (this.optsDirty) {
324 this.calculateOptsWidth();
325 }
326 let openAmount = this.initialOpenAmount - gesture.deltaX;
327 switch (this.sides) {
328 case 2 /* End */:
329 openAmount = Math.max(0, openAmount);
330 break;
331 case 1 /* Start */:
332 openAmount = Math.min(0, openAmount);
333 break;
334 case 3 /* Both */: break;
335 case 0 /* None */: return;
336 default:
337 console.warn('invalid ItemSideFlags value', this.sides);
338 break;
339 }
340 let optsWidth;
341 if (openAmount > this.optsWidthRightSide) {
342 optsWidth = this.optsWidthRightSide;
343 openAmount = optsWidth + (openAmount - optsWidth) * ELASTIC_FACTOR;
344 }
345 else if (openAmount < -this.optsWidthLeftSide) {
346 optsWidth = -this.optsWidthLeftSide;
347 openAmount = optsWidth + (openAmount - optsWidth) * ELASTIC_FACTOR;
348 }
349 this.setOpenAmount(openAmount, false);
350 }
351 onEnd(gesture) {
352 // Restore ion-content scrollY to initial value when gesture ends
353 this.restoreContentScrollY();
354 const velocity = gesture.velocityX;
355 let restingPoint = (this.openAmount > 0)
356 ? this.optsWidthRightSide
357 : -this.optsWidthLeftSide;
358 // Check if the drag didn't clear the buttons mid-point
359 // and we aren't moving fast enough to swipe open
360 const isResetDirection = (this.openAmount > 0) === !(velocity < 0);
361 const isMovingFast = Math.abs(velocity) > 0.3;
362 const isOnCloseZone = Math.abs(this.openAmount) < Math.abs(restingPoint / 2);
363 if (swipeShouldReset(isResetDirection, isMovingFast, isOnCloseZone)) {
364 restingPoint = 0;
365 }
366 const state = this.state;
367 this.setOpenAmount(restingPoint, true);
368 if ((state & 32 /* SwipeEnd */) !== 0 && this.rightOptions) {
369 this.rightOptions.fireSwipeEvent();
370 }
371 else if ((state & 64 /* SwipeStart */) !== 0 && this.leftOptions) {
372 this.leftOptions.fireSwipeEvent();
373 }
374 }
375 calculateOptsWidth() {
376 this.optsWidthRightSide = 0;
377 if (this.rightOptions) {
378 this.rightOptions.style.display = 'flex';
379 this.optsWidthRightSide = this.rightOptions.offsetWidth;
380 this.rightOptions.style.display = '';
381 }
382 this.optsWidthLeftSide = 0;
383 if (this.leftOptions) {
384 this.leftOptions.style.display = 'flex';
385 this.optsWidthLeftSide = this.leftOptions.offsetWidth;
386 this.leftOptions.style.display = '';
387 }
388 this.optsDirty = false;
389 }
390 setOpenAmount(openAmount, isFinal) {
391 if (this.tmr !== undefined) {
392 clearTimeout(this.tmr);
393 this.tmr = undefined;
394 }
395 if (!this.item) {
396 return;
397 }
398 const style = this.item.style;
399 this.openAmount = openAmount;
400 if (isFinal) {
401 style.transition = '';
402 }
403 if (openAmount > 0) {
404 this.state = (openAmount >= (this.optsWidthRightSide + SWIPE_MARGIN))
405 ? 8 /* End */ | 32 /* SwipeEnd */
406 : 8 /* End */;
407 }
408 else if (openAmount < 0) {
409 this.state = (openAmount <= (-this.optsWidthLeftSide - SWIPE_MARGIN))
410 ? 16 /* Start */ | 64 /* SwipeStart */
411 : 16 /* Start */;
412 }
413 else {
414 this.tmr = setTimeout(() => {
415 this.state = 2 /* Disabled */;
416 this.tmr = undefined;
417 }, 600);
418 openSlidingItem = undefined;
419 style.transform = '';
420 return;
421 }
422 style.transform = `translate3d(${-openAmount}px,0,0)`;
423 this.ionDrag.emit({
424 amount: openAmount,
425 ratio: this.getSlidingRatioSync()
426 });
427 }
428 getSlidingRatioSync() {
429 if (this.openAmount > 0) {
430 return this.openAmount / this.optsWidthRightSide;
431 }
432 else if (this.openAmount < 0) {
433 return this.openAmount / this.optsWidthLeftSide;
434 }
435 else {
436 return 0;
437 }
438 }
439 render() {
440 const mode = ionicGlobal.getIonMode(this);
441 return (index.h(index.Host, { class: {
442 [mode]: true,
443 'item-sliding-active-slide': (this.state !== 2 /* Disabled */),
444 'item-sliding-active-options-end': (this.state & 8 /* End */) !== 0,
445 'item-sliding-active-options-start': (this.state & 16 /* Start */) !== 0,
446 'item-sliding-active-swipe-end': (this.state & 32 /* SwipeEnd */) !== 0,
447 'item-sliding-active-swipe-start': (this.state & 64 /* SwipeStart */) !== 0
448 } }));
449 }
450 get el() { return index.getElement(this); }
451 static get watchers() { return {
452 "disabled": ["disabledChanged"]
453 }; }
454};
455const swipeShouldReset = (isResetDirection, isMovingFast, isOnResetZone) => {
456 // The logic required to know when the sliding item should close (openAmount=0)
457 // depends on three booleans (isResetDirection, isMovingFast, isOnResetZone)
458 // and it ended up being too complicated to be written manually without errors
459 // so the truth table is attached below: (0=false, 1=true)
460 // isResetDirection | isMovingFast | isOnResetZone || shouldClose
461 // 0 | 0 | 0 || 0
462 // 0 | 0 | 1 || 1
463 // 0 | 1 | 0 || 0
464 // 0 | 1 | 1 || 0
465 // 1 | 0 | 0 || 0
466 // 1 | 0 | 1 || 1
467 // 1 | 1 | 0 || 1
468 // 1 | 1 | 1 || 1
469 // The resulting expression was generated by resolving the K-map (Karnaugh map):
470 return (!isMovingFast && isOnResetZone) || (isResetDirection && isMovingFast);
471};
472ItemSliding.style = itemSlidingCss;
473
474exports.ion_item_option = ItemOption;
475exports.ion_item_options = ItemOptions;
476exports.ion_item_sliding = ItemSliding;