@rdlabo/ionic-theme-ios27 0.1.0-0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +241 -0
- package/dist/css/components/ion-action-sheet.css +1 -0
- package/dist/css/components/ion-alert.css +1 -0
- package/dist/css/components/ion-button.css +1 -0
- package/dist/css/components/ion-card.css +1 -0
- package/dist/css/components/ion-content.css +1 -0
- package/dist/css/components/ion-datetime.css +1 -0
- package/dist/css/components/ion-fab.css +1 -0
- package/dist/css/components/ion-inputs.css +1 -0
- package/dist/css/components/ion-list.css +1 -0
- package/dist/css/components/ion-loading.css +1 -0
- package/dist/css/components/ion-menu.css +1 -0
- package/dist/css/components/ion-modal.css +1 -0
- package/dist/css/components/ion-picker.css +1 -0
- package/dist/css/components/ion-popover.css +1 -0
- package/dist/css/components/ion-range.css +1 -0
- package/dist/css/components/ion-searchbar.css +1 -0
- package/dist/css/components/ion-segment.css +1 -0
- package/dist/css/components/ion-tabs.css +1 -0
- package/dist/css/components/ion-toast.css +1 -0
- package/dist/css/components/ion-toggle.css +1 -0
- package/dist/css/components/ion-toolbar.css +1 -0
- package/dist/css/default-variables.css +1 -0
- package/dist/css/ionic-theme-ios26-dark-always.css +1 -0
- package/dist/css/ionic-theme-ios26-dark-class.css +1 -0
- package/dist/css/ionic-theme-ios26-dark-system.css +1 -0
- package/dist/css/ionic-theme-ios26.css +1 -0
- package/dist/css/md-ion-list-inset.css +1 -0
- package/dist/css/md-remove-ios-class-effect.css +1 -0
- package/dist/css/utils/api.css +1 -0
- package/dist/css/utils/dark/ion-button.css +1 -0
- package/dist/css/utils/dark/ion-fab.css +1 -0
- package/dist/css/utils/dark/ion-segment.css +1 -0
- package/dist/css/utils/dark/ion-tabs.css +1 -0
- package/dist/css/utils/searchable.css +1 -0
- package/dist/css/utils/structured-list.css +1 -0
- package/dist/css/utils/theme-dark.css +1 -0
- package/dist/css/utils/translucent.css +1 -0
- package/dist/docs.json +234 -0
- package/dist/focus-controller/index.d.ts +6 -0
- package/dist/focus-controller/index.d.ts.map +1 -0
- package/dist/focus-controller/index.js +62 -0
- package/dist/focus-controller /index.d.ts +6 -0
- package/dist/focus-controller /index.d.ts.map +1 -0
- package/dist/focus-controller /index.js +62 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +30 -0
- package/dist/popover/animations/ios.enter.d.ts +4 -0
- package/dist/popover/animations/ios.enter.d.ts.map +1 -0
- package/dist/popover/animations/ios.enter.js +97 -0
- package/dist/popover/animations/ios.leave.d.ts +3 -0
- package/dist/popover/animations/ios.leave.d.ts.map +1 -0
- package/dist/popover/animations/ios.leave.js +60 -0
- package/dist/popover/popover-interface.d.ts +38 -0
- package/dist/popover/popover-interface.d.ts.map +1 -0
- package/dist/popover/popover-interface.js +1 -0
- package/dist/popover/utils.d.ts +37 -0
- package/dist/popover/utils.d.ts.map +1 -0
- package/dist/popover/utils.js +377 -0
- package/dist/sheets-of-glass/animations.d.ts +8 -0
- package/dist/sheets-of-glass/animations.d.ts.map +1 -0
- package/dist/sheets-of-glass/animations.js +97 -0
- package/dist/sheets-of-glass/index.d.ts +3 -0
- package/dist/sheets-of-glass/index.d.ts.map +1 -0
- package/dist/sheets-of-glass/index.js +174 -0
- package/dist/sheets-of-glass/interfaces.d.ts +16 -0
- package/dist/sheets-of-glass/interfaces.d.ts.map +1 -0
- package/dist/sheets-of-glass/interfaces.js +1 -0
- package/dist/tab-bar-searchable/animations/enter.d.ts +8 -0
- package/dist/tab-bar-searchable/animations/enter.d.ts.map +1 -0
- package/dist/tab-bar-searchable/animations/enter.js +73 -0
- package/dist/tab-bar-searchable/animations/leave.d.ts +8 -0
- package/dist/tab-bar-searchable/animations/leave.d.ts.map +1 -0
- package/dist/tab-bar-searchable/animations/leave.js +66 -0
- package/dist/tab-bar-searchable/index.d.ts +4 -0
- package/dist/tab-bar-searchable/index.d.ts.map +1 -0
- package/dist/tab-bar-searchable/index.js +75 -0
- package/dist/tab-bar-searchable/interfaces.d.ts +41 -0
- package/dist/tab-bar-searchable/interfaces.d.ts.map +1 -0
- package/dist/tab-bar-searchable/interfaces.js +5 -0
- package/dist/tab-bar-searchable/utils.d.ts +12 -0
- package/dist/tab-bar-searchable/utils.d.ts.map +1 -0
- package/dist/tab-bar-searchable/utils.js +60 -0
- package/dist/transition/index.d.ts +19 -0
- package/dist/transition/index.d.ts.map +1 -0
- package/dist/transition/index.js +219 -0
- package/dist/transition/ios.transition.d.ts +5 -0
- package/dist/transition/ios.transition.d.ts.map +1 -0
- package/dist/transition/ios.transition.js +609 -0
- package/dist/utils.d.ts +17 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +69 -0
- package/docs/e2e-testing.md +51 -0
- package/docs/eslint.md +73 -0
- package/docs/experimental-animation.md +85 -0
- package/docs/features.md +88 -0
- package/docs/feedback.md +65 -0
- package/docs/ios-18.md +16 -0
- package/docs/migration.md +94 -0
- package/docs/special-markup.md +145 -0
- package/docs/using-ion-item-group.md +47 -0
- package/package.json +63 -0
- package/src/focus-controller/index.ts +123 -0
- package/src/index.ts +33 -0
- package/src/popover/animations/ios.enter.ts +144 -0
- package/src/popover/animations/ios.leave.ts +76 -0
- package/src/popover/popover-interface.ts +44 -0
- package/src/popover/utils.ts +696 -0
- package/src/sheets-of-glass/animations.ts +120 -0
- package/src/sheets-of-glass/index.ts +214 -0
- package/src/sheets-of-glass/interfaces.ts +17 -0
- package/src/styles/components/ion-action-sheet.scss +85 -0
- package/src/styles/components/ion-alert.scss +66 -0
- package/src/styles/components/ion-button.scss +443 -0
- package/src/styles/components/ion-card.scss +7 -0
- package/src/styles/components/ion-content.scss +22 -0
- package/src/styles/components/ion-datetime.scss +9 -0
- package/src/styles/components/ion-fab.scss +104 -0
- package/src/styles/components/ion-inputs.scss +82 -0
- package/src/styles/components/ion-list.scss +44 -0
- package/src/styles/components/ion-loading.scss +11 -0
- package/src/styles/components/ion-menu.scss +110 -0
- package/src/styles/components/ion-modal.scss +42 -0
- package/src/styles/components/ion-picker.scss +4 -0
- package/src/styles/components/ion-popover.scss +33 -0
- package/src/styles/components/ion-range.scss +90 -0
- package/src/styles/components/ion-searchbar.scss +68 -0
- package/src/styles/components/ion-segment.scss +150 -0
- package/src/styles/components/ion-tabs.scss +118 -0
- package/src/styles/components/ion-toast.scss +35 -0
- package/src/styles/components/ion-toggle.scss +65 -0
- package/src/styles/components/ion-toolbar.scss +76 -0
- package/src/styles/default-variables.scss +38 -0
- package/src/styles/ionic-theme-ios26-dark-always.scss +6 -0
- package/src/styles/ionic-theme-ios26-dark-class.scss +6 -0
- package/src/styles/ionic-theme-ios26-dark-system.scss +8 -0
- package/src/styles/ionic-theme-ios26.scss +23 -0
- package/src/styles/md-ion-list-inset.scss +22 -0
- package/src/styles/md-remove-ios-class-effect.scss +14 -0
- package/src/styles/utils/api.scss +146 -0
- package/src/styles/utils/dark/ion-button.scss +58 -0
- package/src/styles/utils/dark/ion-fab.scss +18 -0
- package/src/styles/utils/dark/ion-segment.scss +12 -0
- package/src/styles/utils/dark/ion-tabs.scss +21 -0
- package/src/styles/utils/searchable.scss +0 -0
- package/src/styles/utils/structured-list.scss +170 -0
- package/src/styles/utils/theme-dark.scss +25 -0
- package/src/styles/utils/translucent.scss +95 -0
- package/src/tab-bar-searchable/animations/enter.ts +92 -0
- package/src/tab-bar-searchable/animations/leave.ts +89 -0
- package/src/tab-bar-searchable/index.ts +141 -0
- package/src/tab-bar-searchable/interfaces.ts +28 -0
- package/src/tab-bar-searchable/utils.ts +75 -0
- package/src/transition/index.ts +369 -0
- package/src/transition/ios.transition.ts +966 -0
- package/src/utils.ts +91 -0
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { createGesture } from '@ionic/core';
|
|
2
|
+
import { changeSelectedElement, cloneElement, getStep } from '../utils';
|
|
3
|
+
import { createMoveAnimation, createPreMoveAnimation, getMoveAnimationKeyframe, getScaleAnimation } from './animations';
|
|
4
|
+
const GESTURE_NAME = 'ios26-enable-gesture';
|
|
5
|
+
const ANIMATED_NAME = 'ios26-animated';
|
|
6
|
+
export const registerEffect = (targetElement, effectTagName, selectedClassName, scales) => {
|
|
7
|
+
if (!targetElement.classList.contains('ios')) {
|
|
8
|
+
return undefined;
|
|
9
|
+
}
|
|
10
|
+
let gesture;
|
|
11
|
+
let moveAnimation;
|
|
12
|
+
let currentTouchedElement;
|
|
13
|
+
let clearActivatedTimer;
|
|
14
|
+
let animationPosition = undefined;
|
|
15
|
+
let scaleAnimationPromise;
|
|
16
|
+
let startAnimationPromise;
|
|
17
|
+
let maxVelocity = 0;
|
|
18
|
+
const effectElement = cloneElement(effectTagName);
|
|
19
|
+
const onPointerDown = (event) => {
|
|
20
|
+
clearActivated();
|
|
21
|
+
gesture.destroy();
|
|
22
|
+
createAnimationGesture();
|
|
23
|
+
const onPointerUp = async (e) => {
|
|
24
|
+
clearActivatedTimer = setTimeout(async () => {
|
|
25
|
+
await onEndGesture();
|
|
26
|
+
gesture.destroy();
|
|
27
|
+
createAnimationGesture();
|
|
28
|
+
});
|
|
29
|
+
document.removeEventListener('pointerup', onPointerUp);
|
|
30
|
+
};
|
|
31
|
+
document.addEventListener('pointerup', onPointerUp);
|
|
32
|
+
};
|
|
33
|
+
targetElement.addEventListener('pointerdown', onPointerDown);
|
|
34
|
+
const createAnimationGesture = () => {
|
|
35
|
+
targetElement.classList.add(GESTURE_NAME);
|
|
36
|
+
gesture = createGesture({
|
|
37
|
+
el: targetElement,
|
|
38
|
+
threshold: 0,
|
|
39
|
+
gestureName: `${GESTURE_NAME}_${effectTagName}_${crypto.randomUUID()}`,
|
|
40
|
+
onStart: (event) => onStartGesture(event),
|
|
41
|
+
onMove: (event) => onMoveGesture(event),
|
|
42
|
+
onEnd: () => {
|
|
43
|
+
onEndGesture().then();
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
gesture.enable(true);
|
|
47
|
+
};
|
|
48
|
+
createAnimationGesture();
|
|
49
|
+
const clearActivated = (isEndGesture = false) => {
|
|
50
|
+
if (!currentTouchedElement) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
if (!isEndGesture && !currentTouchedElement.classList.contains(selectedClassName)) {
|
|
54
|
+
currentTouchedElement.click();
|
|
55
|
+
currentTouchedElement.classList.add(selectedClassName);
|
|
56
|
+
}
|
|
57
|
+
currentTouchedElement.classList.remove('ion-activated');
|
|
58
|
+
currentTouchedElement = undefined;
|
|
59
|
+
effectElement.style.display = 'none';
|
|
60
|
+
maxVelocity = 0;
|
|
61
|
+
targetElement.classList.remove(ANIMATED_NAME);
|
|
62
|
+
};
|
|
63
|
+
const onStartGesture = (detail) => {
|
|
64
|
+
currentTouchedElement = detail.event.target.closest(effectTagName) || undefined;
|
|
65
|
+
const tabSelectedElement = targetElement.querySelector(`${effectTagName}.${selectedClassName}`);
|
|
66
|
+
if (currentTouchedElement === undefined || tabSelectedElement === null) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
animationPosition = {
|
|
70
|
+
minPositionX: targetElement.getBoundingClientRect().left,
|
|
71
|
+
maxPositionX: targetElement.getBoundingClientRect().right - tabSelectedElement.clientWidth,
|
|
72
|
+
width: tabSelectedElement.clientWidth,
|
|
73
|
+
positionY: tabSelectedElement.getBoundingClientRect().top,
|
|
74
|
+
};
|
|
75
|
+
targetElement.classList.add(ANIMATED_NAME);
|
|
76
|
+
changeSelectedElement(targetElement, currentTouchedElement, effectTagName, selectedClassName);
|
|
77
|
+
const startAnimation = (() => {
|
|
78
|
+
if (tabSelectedElement === currentTouchedElement) {
|
|
79
|
+
return new Promise((resolve) => resolve());
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
const preMoveAnimation = createPreMoveAnimation(effectElement, tabSelectedElement, currentTouchedElement, animationPosition);
|
|
83
|
+
return preMoveAnimation.play().finally(() => preMoveAnimation.destroy());
|
|
84
|
+
}
|
|
85
|
+
})();
|
|
86
|
+
startAnimationPromise = startAnimation;
|
|
87
|
+
startAnimation.then(() => {
|
|
88
|
+
if (!currentTouchedElement) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
moveAnimation = createMoveAnimation(effectElement, detail, tabSelectedElement, animationPosition);
|
|
92
|
+
moveAnimation.progressStart(true, getStep(currentTouchedElement.getBoundingClientRect().left + currentTouchedElement.clientWidth / 2, animationPosition));
|
|
93
|
+
});
|
|
94
|
+
getScaleAnimation(effectElement).duration(200).to('opacity', 1).to('transform', scales.large).play();
|
|
95
|
+
return true;
|
|
96
|
+
};
|
|
97
|
+
const onMoveGesture = (detail) => {
|
|
98
|
+
if (currentTouchedElement === undefined || !moveAnimation) {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
if (scaleAnimationPromise === undefined) {
|
|
102
|
+
if (Math.abs(detail.velocityX) > maxVelocity) {
|
|
103
|
+
maxVelocity = Math.abs(detail.velocityX);
|
|
104
|
+
}
|
|
105
|
+
if (Math.abs(detail.velocityX) > 0.2) {
|
|
106
|
+
scaleAnimationPromise = getScaleAnimation(effectElement)
|
|
107
|
+
.duration(720)
|
|
108
|
+
.keyframes(getMoveAnimationKeyframe('slowly', scales))
|
|
109
|
+
.play()
|
|
110
|
+
.finally(() => (scaleAnimationPromise = undefined));
|
|
111
|
+
}
|
|
112
|
+
if (maxVelocity > 0.2 && Math.abs(detail.velocityX) < 0.15 && Math.abs(detail.startX - detail.currentX) > 100) {
|
|
113
|
+
scaleAnimationPromise = getScaleAnimation(effectElement)
|
|
114
|
+
.duration(720)
|
|
115
|
+
.keyframes(getMoveAnimationKeyframe(detail.velocityX > 0 ? 'moveRight' : 'moveLeft', scales))
|
|
116
|
+
.play()
|
|
117
|
+
.finally(() => (scaleAnimationPromise = undefined));
|
|
118
|
+
maxVelocity = 0;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
const currentX = detail.currentX;
|
|
122
|
+
const previousY = targetElement.getBoundingClientRect().top + targetElement.getBoundingClientRect().height / 2;
|
|
123
|
+
const nextEl = targetElement.getRootNode().elementFromPoint(currentX, previousY);
|
|
124
|
+
const latestTouchedElement = nextEl?.closest(effectTagName) || undefined;
|
|
125
|
+
if (latestTouchedElement && currentTouchedElement !== latestTouchedElement) {
|
|
126
|
+
currentTouchedElement = latestTouchedElement;
|
|
127
|
+
changeSelectedElement(targetElement, currentTouchedElement, effectTagName, selectedClassName);
|
|
128
|
+
}
|
|
129
|
+
moveAnimation.progressStep(getStep(detail.currentX, animationPosition));
|
|
130
|
+
return true;
|
|
131
|
+
};
|
|
132
|
+
const onEndGesture = async () => {
|
|
133
|
+
if (clearActivatedTimer !== undefined) {
|
|
134
|
+
clearTimeout(clearActivatedTimer);
|
|
135
|
+
clearActivatedTimer = undefined;
|
|
136
|
+
}
|
|
137
|
+
if (currentTouchedElement && !currentTouchedElement.classList.contains(selectedClassName)) {
|
|
138
|
+
currentTouchedElement.click();
|
|
139
|
+
currentTouchedElement.classList.add(selectedClassName);
|
|
140
|
+
}
|
|
141
|
+
if (startAnimationPromise) {
|
|
142
|
+
await startAnimationPromise;
|
|
143
|
+
}
|
|
144
|
+
if (currentTouchedElement === undefined || !moveAnimation) {
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
setTimeout(() => {
|
|
148
|
+
if (!currentTouchedElement) {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
const targetX = currentTouchedElement.getBoundingClientRect().left + currentTouchedElement.clientWidth / 2;
|
|
152
|
+
const step = getStep(targetX, animationPosition);
|
|
153
|
+
moveAnimation.progressStep(step);
|
|
154
|
+
});
|
|
155
|
+
await getScaleAnimation(effectElement).duration(120).to('transform', `scale(1, 0.92)`).play();
|
|
156
|
+
moveAnimation.destroy();
|
|
157
|
+
clearActivated(true);
|
|
158
|
+
return true;
|
|
159
|
+
};
|
|
160
|
+
return {
|
|
161
|
+
destroy: () => {
|
|
162
|
+
targetElement.removeEventListener('pointerdown', onPointerDown);
|
|
163
|
+
if (clearActivatedTimer !== undefined) {
|
|
164
|
+
clearTimeout(clearActivatedTimer);
|
|
165
|
+
clearActivatedTimer = undefined;
|
|
166
|
+
}
|
|
167
|
+
clearActivated();
|
|
168
|
+
if (gesture) {
|
|
169
|
+
gesture.destroy();
|
|
170
|
+
}
|
|
171
|
+
targetElement.classList.remove(GESTURE_NAME);
|
|
172
|
+
},
|
|
173
|
+
};
|
|
174
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface EffectScales {
|
|
2
|
+
small: string;
|
|
3
|
+
medium: string;
|
|
4
|
+
large: string;
|
|
5
|
+
xlarge: string;
|
|
6
|
+
}
|
|
7
|
+
export interface registeredEffect {
|
|
8
|
+
destroy: () => void;
|
|
9
|
+
}
|
|
10
|
+
export interface AnimationPosition {
|
|
11
|
+
minPositionX: number;
|
|
12
|
+
maxPositionX: number;
|
|
13
|
+
width: number;
|
|
14
|
+
positionY: number;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=interfaces.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../../src/sheets-of-glass/interfaces.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ElementReferences, ElementSizes } from '../interfaces';
|
|
2
|
+
import { Animation } from '@ionic/core';
|
|
3
|
+
export declare const createEffectAnimation: (references: ElementReferences, sizes: ElementSizes) => Animation;
|
|
4
|
+
export declare const createSearchContainerAnimation: (references: ElementReferences, sizes: ElementSizes) => Animation;
|
|
5
|
+
export declare const createCloseButtonsAnimation: (references: ElementReferences) => Animation;
|
|
6
|
+
export declare const createTabBarAnimation: (ionTabBar: HTMLElement, references: ElementReferences, sizes: ElementSizes) => Animation;
|
|
7
|
+
export declare const createFabButtonAnimation: (ionFabButton: HTMLElement) => Animation;
|
|
8
|
+
//# sourceMappingURL=enter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enter.d.ts","sourceRoot":"","sources":["../../../src/tab-bar-searchable/animations/enter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAChE,OAAO,EAAE,SAAS,EAAmB,MAAM,aAAa,CAAC;AAIzD,eAAO,MAAM,qBAAqB,GAAI,YAAY,iBAAiB,EAAE,OAAO,YAAY,KAAG,SA0B1F,CAAC;AAEF,eAAO,MAAM,8BAA8B,GAAI,YAAY,iBAAiB,EAAE,OAAO,YAAY,KAAG,SAUnG,CAAC;AAEF,eAAO,MAAM,2BAA2B,GAAI,YAAY,iBAAiB,KAAG,SAO3E,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAI,WAAW,WAAW,EAAE,YAAY,iBAAiB,EAAE,OAAO,YAAY,KAAG,SAwBlH,CAAC;AAEF,eAAO,MAAM,wBAAwB,GAAI,cAAc,WAAW,KAAG,SAWpE,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { createAnimation } from '@ionic/core';
|
|
2
|
+
import { cloneElement } from '../../utils';
|
|
3
|
+
import { ANIMATION_DELAY_CLOSE_BUTTONS, OPACITY_TRANSITION } from '../utils';
|
|
4
|
+
export const createEffectAnimation = (references, sizes) => {
|
|
5
|
+
const effectElement = cloneElement('ion-icon');
|
|
6
|
+
const closeButtonRect = references.closeButtonIcon?.getBoundingClientRect();
|
|
7
|
+
const iconName = references.selectedTabButtonIcon?.getAttribute('name');
|
|
8
|
+
const selectedTabButtonIconRect = references.selectedTabButtonIcon?.getBoundingClientRect();
|
|
9
|
+
return createAnimation()
|
|
10
|
+
.addElement(effectElement)
|
|
11
|
+
.beforeAddWrite(() => {
|
|
12
|
+
effectElement.style.display = 'inline-block';
|
|
13
|
+
references.closeButtonIcon.style.opacity = '0';
|
|
14
|
+
if (iconName && closeButtonRect) {
|
|
15
|
+
effectElement.setAttribute('name', iconName);
|
|
16
|
+
effectElement.style.width = `${closeButtonRect.width}px`;
|
|
17
|
+
effectElement.style.height = `${closeButtonRect.height}px`;
|
|
18
|
+
}
|
|
19
|
+
})
|
|
20
|
+
.afterAddWrite(() => {
|
|
21
|
+
effectElement.style.display = 'none';
|
|
22
|
+
references.closeButtonIcon.style.opacity = '1';
|
|
23
|
+
})
|
|
24
|
+
.fromTo('transform', `translate3d(${selectedTabButtonIconRect.left}px, ${selectedTabButtonIconRect.top}px, 0)`, `translate3d(${closeButtonRect.left}px, ${closeButtonRect.top}px, 0)`);
|
|
25
|
+
};
|
|
26
|
+
export const createSearchContainerAnimation = (references, sizes) => {
|
|
27
|
+
return createAnimation()
|
|
28
|
+
.addElement(references.searchContainer)
|
|
29
|
+
.beforeAddWrite(() => (references.searchContainer.style.transformOrigin = 'right center'))
|
|
30
|
+
.fromTo('transform', `scale(${sizes.fabButton.width / sizes.searchContainer.width}, ${sizes.fabButton.height / sizes.searchContainer.height})`, 'scale(1)')
|
|
31
|
+
.fromTo('opacity', '0.2', '1');
|
|
32
|
+
};
|
|
33
|
+
export const createCloseButtonsAnimation = (references) => {
|
|
34
|
+
return createAnimation()
|
|
35
|
+
.delay(ANIMATION_DELAY_CLOSE_BUTTONS)
|
|
36
|
+
.addElement(references.closeButtons)
|
|
37
|
+
.beforeAddWrite(() => (references.closeButtons.style.transformOrigin = 'left center'))
|
|
38
|
+
.afterClearStyles(['transform', 'transform-origin'])
|
|
39
|
+
.fromTo('transform', 'scale(1.5, 1)', 'scale(1)');
|
|
40
|
+
};
|
|
41
|
+
export const createTabBarAnimation = (ionTabBar, references, sizes) => {
|
|
42
|
+
return createAnimation()
|
|
43
|
+
.addElement(ionTabBar)
|
|
44
|
+
.beforeAddWrite(() => {
|
|
45
|
+
ionTabBar.querySelectorAll('ion-tab-button').forEach((element) => {
|
|
46
|
+
element.style.transition = OPACITY_TRANSITION;
|
|
47
|
+
element.style.opacity = '0';
|
|
48
|
+
});
|
|
49
|
+
references.selectedTabButton.classList.remove('tab-selected');
|
|
50
|
+
const iconName = references.selectedTabButtonIcon?.getAttribute('name');
|
|
51
|
+
if (iconName) {
|
|
52
|
+
references.closeButtonIcon?.setAttribute('name', iconName);
|
|
53
|
+
}
|
|
54
|
+
})
|
|
55
|
+
.afterAddWrite(() => {
|
|
56
|
+
references.selectedTabButton.classList.add('tab-selected');
|
|
57
|
+
ionTabBar.style.pointerEvents = 'none';
|
|
58
|
+
})
|
|
59
|
+
.fromTo('transform', 'scale(1)', `scale(${sizes.closeButton.width / sizes.tabBar.width}, ${sizes.closeButton.height / sizes.tabBar.height})`)
|
|
60
|
+
.fromTo('opacity', '1', '0');
|
|
61
|
+
};
|
|
62
|
+
export const createFabButtonAnimation = (ionFabButton) => {
|
|
63
|
+
return createAnimation()
|
|
64
|
+
.addElement(ionFabButton)
|
|
65
|
+
.beforeAddWrite(() => {
|
|
66
|
+
ionFabButton.style.transformOrigin = 'center right';
|
|
67
|
+
ionFabButton.querySelector('ion-icon')?.style.setProperty('opacity', '0');
|
|
68
|
+
})
|
|
69
|
+
.afterAddWrite(() => {
|
|
70
|
+
ionFabButton.style.pointerEvents = 'none';
|
|
71
|
+
})
|
|
72
|
+
.fromTo('opacity', '1', '0');
|
|
73
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ElementReferences, ElementSizes } from '../interfaces';
|
|
2
|
+
import { Animation } from '@ionic/core';
|
|
3
|
+
export declare const createReverseEffectAnimation: (references: ElementReferences, searchableElementSizes: ElementSizes, colorSelected: string) => Animation;
|
|
4
|
+
export declare const createReverseSearchContainerAnimation: (references: ElementReferences, sizes: ElementSizes) => Animation;
|
|
5
|
+
export declare const createReverseCloseButtonsAnimation: (references: ElementReferences) => Animation;
|
|
6
|
+
export declare const createReverseTabBarAnimation: (ionTabBar: HTMLElement, references: ElementReferences, sizes: ElementSizes) => Animation;
|
|
7
|
+
export declare const createReverseFabButtonAnimation: (ionFabButton: HTMLElement, references: ElementSizes) => Animation;
|
|
8
|
+
//# sourceMappingURL=leave.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"leave.d.ts","sourceRoot":"","sources":["../../../src/tab-bar-searchable/animations/leave.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAChE,OAAO,EAAE,SAAS,EAAmB,MAAM,aAAa,CAAC;AAIzD,eAAO,MAAM,4BAA4B,GACvC,YAAY,iBAAiB,EAC7B,wBAAwB,YAAY,EACpC,eAAe,MAAM,KACpB,SAyBF,CAAC;AAEF,eAAO,MAAM,qCAAqC,GAAI,YAAY,iBAAiB,EAAE,OAAO,YAAY,KAAG,SAU1G,CAAC;AAEF,eAAO,MAAM,kCAAkC,GAAI,YAAY,iBAAiB,KAAG,SAOlF,CAAC;AAEF,eAAO,MAAM,4BAA4B,GAAI,WAAW,WAAW,EAAE,YAAY,iBAAiB,EAAE,OAAO,YAAY,KAAG,SAiBzH,CAAC;AAEF,eAAO,MAAM,+BAA+B,GAAI,cAAc,WAAW,EAAE,YAAY,YAAY,KAAG,SAYrG,CAAC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { createAnimation } from '@ionic/core';
|
|
2
|
+
import { cloneElement } from '../../utils';
|
|
3
|
+
import { ANIMATION_DELAY_CLOSE_BUTTONS, OPACITY_TRANSITION } from '../utils';
|
|
4
|
+
export const createReverseEffectAnimation = (references, searchableElementSizes, colorSelected) => {
|
|
5
|
+
const effectElement = cloneElement('ion-icon');
|
|
6
|
+
const closeButtonRect = references.closeButtonIcon?.getBoundingClientRect();
|
|
7
|
+
return createAnimation()
|
|
8
|
+
.addElement(effectElement)
|
|
9
|
+
.beforeAddWrite(() => {
|
|
10
|
+
effectElement.style.display = 'inline-block';
|
|
11
|
+
references.closeButtonIcon.style.opacity = '0';
|
|
12
|
+
if (searchableElementSizes.selectedTabButtonIcon) {
|
|
13
|
+
effectElement.style.width = `${searchableElementSizes.selectedTabButtonIcon.width}px`;
|
|
14
|
+
effectElement.style.height = `${searchableElementSizes.selectedTabButtonIcon.height}px`;
|
|
15
|
+
effectElement.style.color = colorSelected;
|
|
16
|
+
}
|
|
17
|
+
})
|
|
18
|
+
.afterAddWrite(() => {
|
|
19
|
+
effectElement.style.display = 'none';
|
|
20
|
+
references.closeButtonIcon.style.opacity = '1';
|
|
21
|
+
effectElement.style.color = '';
|
|
22
|
+
})
|
|
23
|
+
.fromTo('transform', `translate3d(${closeButtonRect.left}px, ${closeButtonRect.top}px, 0)`, `translate3d(${searchableElementSizes.selectedTabButtonIcon.left}px, ${searchableElementSizes.selectedTabButtonIcon.top}px, 0)`);
|
|
24
|
+
};
|
|
25
|
+
export const createReverseSearchContainerAnimation = (references, sizes) => {
|
|
26
|
+
return createAnimation()
|
|
27
|
+
.addElement(references.searchContainer)
|
|
28
|
+
.beforeAddWrite(() => (references.searchContainer.style.transformOrigin = 'right center'))
|
|
29
|
+
.fromTo('transform', 'scale(1)', `scale(${sizes.fabButton.width / sizes.searchContainer.width}, ${sizes.fabButton.height / sizes.searchContainer.height})`)
|
|
30
|
+
.fromTo('opacity', '1', '0.2');
|
|
31
|
+
};
|
|
32
|
+
export const createReverseCloseButtonsAnimation = (references) => {
|
|
33
|
+
return createAnimation()
|
|
34
|
+
.delay(ANIMATION_DELAY_CLOSE_BUTTONS)
|
|
35
|
+
.addElement(references.closeButtons)
|
|
36
|
+
.beforeAddWrite(() => (references.closeButtons.style.transformOrigin = 'left center'))
|
|
37
|
+
.afterClearStyles(['transform', 'transform-origin'])
|
|
38
|
+
.fromTo('transform', 'scale(1)', 'scale(1.5, 1)');
|
|
39
|
+
};
|
|
40
|
+
export const createReverseTabBarAnimation = (ionTabBar, references, sizes) => {
|
|
41
|
+
return createAnimation()
|
|
42
|
+
.addElement(ionTabBar)
|
|
43
|
+
.beforeAddWrite(() => {
|
|
44
|
+
ionTabBar.style.pointerEvents = 'auto';
|
|
45
|
+
ionTabBar.querySelectorAll('ion-tab-button').forEach((element) => {
|
|
46
|
+
element.style.transition = OPACITY_TRANSITION;
|
|
47
|
+
element.style.opacity = '1';
|
|
48
|
+
});
|
|
49
|
+
})
|
|
50
|
+
.afterClearStyles(['transform', 'opacity'])
|
|
51
|
+
.fromTo('transform', `scale(${sizes.closeButton.width / sizes.tabBar.width}, ${sizes.closeButton.height / sizes.tabBar.height})`, 'scale(1)')
|
|
52
|
+
.fromTo('opacity', '0', '1');
|
|
53
|
+
};
|
|
54
|
+
export const createReverseFabButtonAnimation = (ionFabButton, references) => {
|
|
55
|
+
return createAnimation()
|
|
56
|
+
.addElement(ionFabButton)
|
|
57
|
+
.beforeAddWrite(() => {
|
|
58
|
+
ionFabButton.querySelector('ion-icon')?.style.setProperty('opacity', '1');
|
|
59
|
+
ionFabButton.style.transformOrigin = 'center right';
|
|
60
|
+
})
|
|
61
|
+
.afterAddWrite(() => {
|
|
62
|
+
ionFabButton.style.pointerEvents = 'auto';
|
|
63
|
+
})
|
|
64
|
+
.fromTo('opacity', '0', '1')
|
|
65
|
+
.fromTo('transform', `scale(${references.searchContainer.height / references.fabButton.height})`, 'scale(1)');
|
|
66
|
+
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { TabBarSearchableFunction } from './interfaces';
|
|
2
|
+
export * from './interfaces';
|
|
3
|
+
export declare const attachTabBarSearchable: (ionTabBar: HTMLElement, ionFabButton: HTMLElement, ionFooter: HTMLElement) => TabBarSearchableFunction;
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tab-bar-searchable/index.ts"],"names":[],"mappings":"AASA,OAAO,EAAwB,wBAAwB,EAAwB,MAAM,cAAc,CAAC;AAgBpG,cAAc,cAAc,CAAC;AAqB7B,eAAO,MAAM,sBAAsB,GACjC,WAAW,WAAW,EACtB,cAAc,WAAW,EACzB,WAAW,WAAW,KACrB,wBAsBF,CAAC"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { createAnimation } from '@ionic/core';
|
|
2
|
+
import { ANIMATION_DELAY_BASE, ANIMATION_DURATION, ANIMATION_EASING, getElementReferences, getElementSizes, throwErrorByFailedClickElement, } from './utils';
|
|
3
|
+
import { TabBarSearchableType } from './interfaces';
|
|
4
|
+
import { createCloseButtonsAnimation, createEffectAnimation, createFabButtonAnimation, createSearchContainerAnimation, createTabBarAnimation, } from './animations/enter';
|
|
5
|
+
import { createReverseCloseButtonsAnimation, createReverseEffectAnimation, createReverseFabButtonAnimation, createReverseSearchContainerAnimation, createReverseTabBarAnimation, } from './animations/leave';
|
|
6
|
+
export * from './interfaces';
|
|
7
|
+
export const attachTabBarSearchable = (ionTabBar, ionFabButton, ionFooter) => {
|
|
8
|
+
if (!ionTabBar || !ionFabButton || !ionFooter) {
|
|
9
|
+
throw new Error('TabBarSearchable should be defined with props');
|
|
10
|
+
}
|
|
11
|
+
ionFooter.style.pointerEvents = 'none';
|
|
12
|
+
ionFooter.style.opacity = '0';
|
|
13
|
+
ionTabBar.style.transformOrigin = 'left center';
|
|
14
|
+
let searchableEventCache;
|
|
15
|
+
return async (event, type) => {
|
|
16
|
+
if (type === TabBarSearchableType.Enter) {
|
|
17
|
+
searchableEventCache = await enterEvent(event, ionTabBar, ionFabButton, ionFooter);
|
|
18
|
+
}
|
|
19
|
+
else if (searchableEventCache !== undefined) {
|
|
20
|
+
await leaveEvent(event, searchableEventCache, ionTabBar, ionFabButton, ionFooter);
|
|
21
|
+
searchableEventCache = undefined;
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
throw new Error('TabBarSearchableType.Leave should be run after TabBarSearchableType.Enter');
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
const enterEvent = async (event, ionTabBar, ionFabButton, ionFooter) => {
|
|
29
|
+
if (!event.target?.closest('ion-fab-button')) {
|
|
30
|
+
throw throwErrorByFailedClickElement('ion-fab-button');
|
|
31
|
+
}
|
|
32
|
+
const references = getElementReferences(ionTabBar, ionFooter);
|
|
33
|
+
const sizes = getElementSizes(ionTabBar, ionFabButton, references);
|
|
34
|
+
const colorSelected = references.selectedTabButton
|
|
35
|
+
? getComputedStyle(references.selectedTabButton).getPropertyValue('--color-selected').trim()
|
|
36
|
+
: '';
|
|
37
|
+
const effectAnimation = createEffectAnimation(references, sizes);
|
|
38
|
+
const searchContainerAnimation = createSearchContainerAnimation(references, sizes);
|
|
39
|
+
const closeButtonsAnimation = createCloseButtonsAnimation(references);
|
|
40
|
+
const tabBarAnimation = createTabBarAnimation(ionTabBar, references, sizes);
|
|
41
|
+
const fabButtonAnimation = createFabButtonAnimation(ionFabButton);
|
|
42
|
+
await createAnimation()
|
|
43
|
+
.delay(ANIMATION_DELAY_BASE)
|
|
44
|
+
.duration(ANIMATION_DURATION)
|
|
45
|
+
.easing(ANIMATION_EASING)
|
|
46
|
+
.addElement(ionFooter)
|
|
47
|
+
.afterAddWrite(() => (ionFooter.style.pointerEvents = 'auto'))
|
|
48
|
+
.fromTo('opacity', '0.8', '1')
|
|
49
|
+
.addAnimation([tabBarAnimation, fabButtonAnimation, searchContainerAnimation, effectAnimation, closeButtonsAnimation])
|
|
50
|
+
.play();
|
|
51
|
+
return {
|
|
52
|
+
elementSizes: sizes,
|
|
53
|
+
colorSelected,
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
const leaveEvent = async (event, searchableEventCache, ionTabBar, ionFabButton, ionFooter) => {
|
|
57
|
+
if (!event.target?.closest('ion-buttons[slot=start] ion-button')) {
|
|
58
|
+
throw throwErrorByFailedClickElement('ion-buttons[slot=start] ion-button');
|
|
59
|
+
}
|
|
60
|
+
const references = getElementReferences(ionTabBar, ionFooter);
|
|
61
|
+
const effectAnimation = createReverseEffectAnimation(references, searchableEventCache.elementSizes, searchableEventCache.colorSelected);
|
|
62
|
+
const searchContainerAnimation = createReverseSearchContainerAnimation(references, searchableEventCache.elementSizes);
|
|
63
|
+
const closeButtonsAnimation = createReverseCloseButtonsAnimation(references);
|
|
64
|
+
const tabBarAnimation = createReverseTabBarAnimation(ionTabBar, references, searchableEventCache.elementSizes);
|
|
65
|
+
const fabButtonAnimation = createReverseFabButtonAnimation(ionFabButton, searchableEventCache.elementSizes);
|
|
66
|
+
await createAnimation()
|
|
67
|
+
.delay(ANIMATION_DELAY_BASE)
|
|
68
|
+
.duration(ANIMATION_DURATION)
|
|
69
|
+
.easing(ANIMATION_EASING)
|
|
70
|
+
.addElement(ionFooter)
|
|
71
|
+
.afterAddWrite(() => (ionFooter.style.pointerEvents = 'none'))
|
|
72
|
+
.fromTo('opacity', '1', '0')
|
|
73
|
+
.addAnimation([tabBarAnimation, fabButtonAnimation, searchContainerAnimation, effectAnimation, closeButtonsAnimation])
|
|
74
|
+
.play();
|
|
75
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export declare enum TabBarSearchableType {
|
|
2
|
+
Enter = "enter",
|
|
3
|
+
Leave = "leave"
|
|
4
|
+
}
|
|
5
|
+
export type TabBarSearchableFunction = (event: Event, type: TabBarSearchableType) => Promise<void>;
|
|
6
|
+
export interface SearchableEventCache {
|
|
7
|
+
elementSizes: ElementSizes;
|
|
8
|
+
colorSelected: string;
|
|
9
|
+
}
|
|
10
|
+
export interface ElementSizes {
|
|
11
|
+
tabBar: {
|
|
12
|
+
width: number;
|
|
13
|
+
height: number;
|
|
14
|
+
};
|
|
15
|
+
closeButton: {
|
|
16
|
+
width: number;
|
|
17
|
+
height: number;
|
|
18
|
+
};
|
|
19
|
+
fabButton: {
|
|
20
|
+
width: number;
|
|
21
|
+
height: number;
|
|
22
|
+
};
|
|
23
|
+
searchContainer: {
|
|
24
|
+
width: number;
|
|
25
|
+
height: number;
|
|
26
|
+
};
|
|
27
|
+
selectedTabButtonIcon: {
|
|
28
|
+
width: number;
|
|
29
|
+
height: number;
|
|
30
|
+
top: number;
|
|
31
|
+
left: number;
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export interface ElementReferences {
|
|
35
|
+
searchContainer: HTMLElement;
|
|
36
|
+
closeButtons: HTMLElement;
|
|
37
|
+
selectedTabButton: HTMLElement;
|
|
38
|
+
selectedTabButtonIcon: HTMLElement;
|
|
39
|
+
closeButtonIcon: HTMLElement;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=interfaces.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../../src/tab-bar-searchable/interfaces.ts"],"names":[],"mappings":"AAAA,oBAAY,oBAAoB;IAC9B,KAAK,UAAU;IACf,KAAK,UAAU;CAChB;AAED,MAAM,MAAM,wBAAwB,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,oBAAoB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAEnG,MAAM,WAAW,oBAAoB;IACnC,YAAY,EAAE,YAAY,CAAC;IAC3B,aAAa,EAAE,MAAM,CAAC;CACvB;AAGD,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1C,WAAW,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C,SAAS,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,eAAe,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACnD,qBAAqB,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CACrF;AAED,MAAM,WAAW,iBAAiB;IAChC,eAAe,EAAE,WAAW,CAAC;IAC7B,YAAY,EAAE,WAAW,CAAC;IAC1B,iBAAiB,EAAE,WAAW,CAAC;IAC/B,qBAAqB,EAAE,WAAW,CAAC;IACnC,eAAe,EAAE,WAAW,CAAC;CAC9B"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ElementReferences, ElementSizes } from './interfaces';
|
|
2
|
+
export declare const ANIMATION_DURATION = 400;
|
|
3
|
+
export declare const ANIMATION_DELAY_BASE = 140;
|
|
4
|
+
export declare const ANIMATION_DELAY_CLOSE_BUTTONS = 240;
|
|
5
|
+
export declare const ANIMATION_EASING = "cubic-bezier(0, 1, 0.22, 1)";
|
|
6
|
+
export declare const OPACITY_TRANSITION = "opacity 140ms ease";
|
|
7
|
+
export declare const throwErrorByFailedClickElement: (selector: string) => Error;
|
|
8
|
+
export declare const throwErrorByFailedExistElement: (selector: string) => Error;
|
|
9
|
+
export declare const getElement: (docs: HTMLElement, selector: string) => HTMLElement;
|
|
10
|
+
export declare const getElementReferences: (ionTabBar: HTMLElement, ionFooter: HTMLElement) => ElementReferences;
|
|
11
|
+
export declare const getElementSizes: (ionTabBar: HTMLElement, ionFabButton: HTMLElement, references: ElementReferences) => ElementSizes;
|
|
12
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/tab-bar-searchable/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE/D,eAAO,MAAM,kBAAkB,MAAM,CAAC;AACtC,eAAO,MAAM,oBAAoB,MAAM,CAAC;AACxC,eAAO,MAAM,6BAA6B,MAAM,CAAC;AACjD,eAAO,MAAM,gBAAgB,gCAAgC,CAAC;AAC9D,eAAO,MAAM,kBAAkB,uBAAuB,CAAC;AAEvD,eAAO,MAAM,8BAA8B,GAAI,UAAU,MAAM,KAAG,KAEjE,CAAC;AAEF,eAAO,MAAM,8BAA8B,GAAI,UAAU,MAAM,KAAG,KAEjE,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,MAAM,WAAW,EAAE,UAAU,MAAM,KAAG,WAMhE,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,WAAW,WAAW,EAAE,WAAW,WAAW,KAAG,iBA0BrF,CAAC;AAKF,eAAO,MAAM,eAAe,GAAI,WAAW,WAAW,EAAE,cAAc,WAAW,EAAE,YAAY,iBAAiB,KAAG,YAmBlH,CAAC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export const ANIMATION_DURATION = 400;
|
|
2
|
+
export const ANIMATION_DELAY_BASE = 140;
|
|
3
|
+
export const ANIMATION_DELAY_CLOSE_BUTTONS = 240;
|
|
4
|
+
export const ANIMATION_EASING = 'cubic-bezier(0, 1, 0.22, 1)';
|
|
5
|
+
export const OPACITY_TRANSITION = 'opacity 140ms ease';
|
|
6
|
+
export const throwErrorByFailedClickElement = (selector) => {
|
|
7
|
+
return new Error('Expected click element to be inside `' + selector + '`');
|
|
8
|
+
};
|
|
9
|
+
export const throwErrorByFailedExistElement = (selector) => {
|
|
10
|
+
return new Error('Expected element `' + selector + '` to exist');
|
|
11
|
+
};
|
|
12
|
+
export const getElement = (docs, selector) => {
|
|
13
|
+
const el = docs.querySelector(selector);
|
|
14
|
+
if (!el) {
|
|
15
|
+
throw throwErrorByFailedClickElement(selector);
|
|
16
|
+
}
|
|
17
|
+
return el;
|
|
18
|
+
};
|
|
19
|
+
export const getElementReferences = (ionTabBar, ionFooter) => {
|
|
20
|
+
const searchContainer = getElement(ionFooter, 'ion-searchbar .searchbar-input-container');
|
|
21
|
+
const closeButtons = getElement(ionFooter, 'ion-buttons[slot=start]');
|
|
22
|
+
const selectedTabButton = ionTabBar.querySelector('ion-tab-button.tab-selected');
|
|
23
|
+
const selectedTabButtonIcon = selectedTabButton?.querySelector('ion-icon');
|
|
24
|
+
const closeButtonIcon = closeButtons.querySelector('ion-icon');
|
|
25
|
+
if (!selectedTabButton) {
|
|
26
|
+
throw throwErrorByFailedExistElement('ion-tab-button.tab-selected');
|
|
27
|
+
}
|
|
28
|
+
if (!selectedTabButtonIcon) {
|
|
29
|
+
throw throwErrorByFailedExistElement('ion-tab-button.tab-selected ion-icon');
|
|
30
|
+
}
|
|
31
|
+
if (!closeButtonIcon) {
|
|
32
|
+
throw throwErrorByFailedExistElement('ion-buttons[slot=start] ion-button ion-icon');
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
searchContainer,
|
|
36
|
+
closeButtons,
|
|
37
|
+
selectedTabButton,
|
|
38
|
+
selectedTabButtonIcon,
|
|
39
|
+
closeButtonIcon,
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
export const getElementSizes = (ionTabBar, ionFabButton, references) => {
|
|
43
|
+
const tabBarRect = ionTabBar.getBoundingClientRect();
|
|
44
|
+
const fabButtonRect = ionFabButton.getBoundingClientRect();
|
|
45
|
+
const closeButtonRect = references.closeButtons.getBoundingClientRect();
|
|
46
|
+
const searchContainerRect = references.searchContainer.getBoundingClientRect();
|
|
47
|
+
const selectedTabButtonIconRect = references.selectedTabButtonIcon.getBoundingClientRect();
|
|
48
|
+
return {
|
|
49
|
+
tabBar: { width: tabBarRect.width, height: tabBarRect.height },
|
|
50
|
+
closeButton: { width: closeButtonRect.width, height: closeButtonRect.height },
|
|
51
|
+
fabButton: { width: fabButtonRect.width, height: fabButtonRect.height },
|
|
52
|
+
searchContainer: { width: searchContainerRect.width, height: searchContainerRect.height },
|
|
53
|
+
selectedTabButtonIcon: {
|
|
54
|
+
width: selectedTabButtonIconRect.width,
|
|
55
|
+
height: selectedTabButtonIconRect.height,
|
|
56
|
+
top: selectedTabButtonIconRect.top,
|
|
57
|
+
left: selectedTabButtonIconRect.left,
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { NavOptions } from '@ionic/core';
|
|
2
|
+
import type { Animation } from '@ionic/core';
|
|
3
|
+
export declare const transition: (opts: TransitionOptions) => Promise<TransitionResult>;
|
|
4
|
+
export declare const lifecycle: (el: HTMLElement | undefined, eventName: string) => void;
|
|
5
|
+
export declare const waitForMount: () => Promise<void>;
|
|
6
|
+
export declare const deepReady: (el: any | undefined) => Promise<void>;
|
|
7
|
+
export declare const setPageHidden: (el: HTMLElement, hidden: boolean) => void;
|
|
8
|
+
export declare const getIonPageElement: (element: HTMLElement) => Element;
|
|
9
|
+
export interface TransitionOptions extends NavOptions {
|
|
10
|
+
progressCallback?: (ani: Animation | undefined) => void;
|
|
11
|
+
baseEl: any;
|
|
12
|
+
enteringEl: HTMLElement;
|
|
13
|
+
leavingEl: HTMLElement | undefined;
|
|
14
|
+
}
|
|
15
|
+
export interface TransitionResult {
|
|
16
|
+
hasCompleted: boolean;
|
|
17
|
+
animation?: Animation;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/transition/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAgB,MAAM,aAAa,CAAC;AAC5D,OAAO,KAAK,EAAE,SAAS,EAAoB,MAAM,aAAa,CAAC;AAmB/D,eAAO,MAAM,UAAU,GAAI,MAAM,iBAAiB,KAAG,OAAO,CAAC,gBAAgB,CAyB5E,CAAC;AAkKF,eAAO,MAAM,SAAS,GAAI,IAAI,WAAW,GAAG,SAAS,EAAE,WAAW,MAAM,SAQvE,CAAC;AAeF,eAAO,MAAM,YAAY,QAAO,OAAO,CAAC,IAAI,CAE3C,CAAC;AAEF,eAAO,MAAM,SAAS,GAAU,IAAI,GAAG,GAAG,SAAS,KAAG,OAAO,CAAC,IAAI,CAyBjE,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,IAAI,WAAW,EAAE,QAAQ,OAAO,SAS7D,CAAC;AA6CF,eAAO,MAAM,iBAAiB,GAAI,SAAS,WAAW,YAWrD,CAAC;AA4BF,MAAM,WAAW,iBAAkB,SAAQ,UAAU;IACnD,gBAAgB,CAAC,EAAE,CAAC,GAAG,EAAE,SAAS,GAAG,SAAS,KAAK,IAAI,CAAC;IACxD,MAAM,EAAE,GAAG,CAAC;IACZ,UAAU,EAAE,WAAW,CAAC;IACxB,SAAS,EAAE,WAAW,GAAG,SAAS,CAAC;CACpC;AAED,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,OAAO,CAAC;IACtB,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB"}
|