mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
Compare commits
16 Commits
v7.4.3
...
ld/datetim
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
726e4aeae7 | ||
|
|
eee2115fd2 | ||
|
|
d0057352fe | ||
|
|
c70432e693 | ||
|
|
a1690441e5 | ||
|
|
e6031fbef0 | ||
|
|
d5f0c776df | ||
|
|
00767a02e4 | ||
|
|
3259da0de1 | ||
|
|
470c119a05 | ||
|
|
b297529afc | ||
|
|
7375dd6aba | ||
|
|
1167a9325f | ||
|
|
dc75392e9d | ||
|
|
865bd2a004 | ||
|
|
2429caa168 |
11
.github/workflows/stencil-nightly.yml
vendored
11
.github/workflows/stencil-nightly.yml
vendored
@@ -8,7 +8,12 @@ on:
|
||||
# at 6:00 UTC (6:00 am UTC)
|
||||
- cron: '00 06 * * 1-5'
|
||||
workflow_dispatch:
|
||||
# allows for manual invocations in the GitHub UI
|
||||
inputs:
|
||||
npm_release_tag:
|
||||
required: true
|
||||
type: string
|
||||
description: What version should be pulled from NPM?
|
||||
default: nightly
|
||||
|
||||
# When pushing a new commit we should
|
||||
# cancel the previous test run to not
|
||||
@@ -24,7 +29,7 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/build-core-stencil-prerelease
|
||||
with:
|
||||
stencil-version: nightly
|
||||
stencil-version: ${{ inputs.npm_release_tag || 'nightly' }}
|
||||
|
||||
test-core-clean-build:
|
||||
needs: [build-core-with-stencil-nightly]
|
||||
@@ -47,7 +52,7 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/test-core-spec
|
||||
with:
|
||||
stencil-version: nightly
|
||||
stencil-version: ${{ inputs.npm_release_tag || 'nightly' }}
|
||||
|
||||
test-core-screenshot:
|
||||
strategy:
|
||||
|
||||
28
core/package-lock.json
generated
28
core/package-lock.json
generated
@@ -9,13 +9,13 @@
|
||||
"version": "7.4.3",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@stencil/core": "^4.4.0",
|
||||
"@stencil/core": "^4.4.1",
|
||||
"ionicons": "7.1.0",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@axe-core/playwright": "^4.7.3",
|
||||
"@capacitor/core": "^5.4.1",
|
||||
"@capacitor/core": "^5.4.2",
|
||||
"@capacitor/haptics": "^5.0.6",
|
||||
"@capacitor/keyboard": "^5.0.6",
|
||||
"@capacitor/status-bar": "^5.0.6",
|
||||
@@ -607,9 +607,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@capacitor/core": {
|
||||
"version": "5.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@capacitor/core/-/core-5.4.1.tgz",
|
||||
"integrity": "sha512-QG9gORuxw2WNcVpLHT1W3LzACOJvFWRuHcz4b9edzxehSELqiSQ4DoGWLp4PuNBBp2oV/fGA4FMNmfZ1jIAAWg==",
|
||||
"version": "5.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@capacitor/core/-/core-5.4.2.tgz",
|
||||
"integrity": "sha512-XbR1vldJFzBWHeoGPpgfNy3Zhjf0NxXdHEaGNANWVBg0ZWG2gwFr1dcRALUUQtbwrEEkCCNiLYg4YiQPRk7SEQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"tslib": "^2.1.0"
|
||||
@@ -1630,9 +1630,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@stencil/core": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.4.0.tgz",
|
||||
"integrity": "sha512-YlLyCqGBsMEuZb3XTO/STT0TX9eSwjoVhCJgtjVfQOF+ebIMVlojTh40CmDveWiWbth687cbr6S2heeussV8Sg==",
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.4.1.tgz",
|
||||
"integrity": "sha512-SirGcrb5yKHCn2BwdM7HGVXuvCdmwiXlVczEj8jJxQIm42CAUQCUECxtZidTzp+oZBZnWLnoAvfanchJsgkQzA==",
|
||||
"bin": {
|
||||
"stencil": "bin/stencil"
|
||||
},
|
||||
@@ -10802,9 +10802,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"@capacitor/core": {
|
||||
"version": "5.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@capacitor/core/-/core-5.4.1.tgz",
|
||||
"integrity": "sha512-QG9gORuxw2WNcVpLHT1W3LzACOJvFWRuHcz4b9edzxehSELqiSQ4DoGWLp4PuNBBp2oV/fGA4FMNmfZ1jIAAWg==",
|
||||
"version": "5.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@capacitor/core/-/core-5.4.2.tgz",
|
||||
"integrity": "sha512-XbR1vldJFzBWHeoGPpgfNy3Zhjf0NxXdHEaGNANWVBg0ZWG2gwFr1dcRALUUQtbwrEEkCCNiLYg4YiQPRk7SEQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"tslib": "^2.1.0"
|
||||
@@ -11536,9 +11536,9 @@
|
||||
"requires": {}
|
||||
},
|
||||
"@stencil/core": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.4.0.tgz",
|
||||
"integrity": "sha512-YlLyCqGBsMEuZb3XTO/STT0TX9eSwjoVhCJgtjVfQOF+ebIMVlojTh40CmDveWiWbth687cbr6S2heeussV8Sg=="
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.4.1.tgz",
|
||||
"integrity": "sha512-SirGcrb5yKHCn2BwdM7HGVXuvCdmwiXlVczEj8jJxQIm42CAUQCUECxtZidTzp+oZBZnWLnoAvfanchJsgkQzA=="
|
||||
},
|
||||
"@stencil/react-output-target": {
|
||||
"version": "0.5.3",
|
||||
|
||||
@@ -31,13 +31,13 @@
|
||||
"loader/"
|
||||
],
|
||||
"dependencies": {
|
||||
"@stencil/core": "^4.4.0",
|
||||
"@stencil/core": "^4.4.1",
|
||||
"ionicons": "7.1.0",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@axe-core/playwright": "^4.7.3",
|
||||
"@capacitor/core": "^5.4.1",
|
||||
"@capacitor/core": "^5.4.2",
|
||||
"@capacitor/haptics": "^5.0.6",
|
||||
"@capacitor/keyboard": "^5.0.6",
|
||||
"@capacitor/status-bar": "^5.0.6",
|
||||
|
||||
1
core/src/components.d.ts
vendored
1
core/src/components.d.ts
vendored
@@ -6976,6 +6976,7 @@ declare namespace LocalJSX {
|
||||
*/
|
||||
"mode"?: "ios" | "md";
|
||||
"onIonTabBarChanged"?: (event: IonTabBarCustomEvent<TabBarChangedEventDetail>) => void;
|
||||
"onIonTabBarLoaded"?: (event: IonTabBarCustomEvent<void>) => void;
|
||||
/**
|
||||
* The selected tab component
|
||||
*/
|
||||
|
||||
@@ -211,6 +211,10 @@ export class Checkbox implements ComponentInterface {
|
||||
};
|
||||
|
||||
private onClick = (ev: MouseEvent) => {
|
||||
if (this.disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.toggleChecked(ev);
|
||||
};
|
||||
|
||||
|
||||
24
core/src/components/checkbox/test/checkbox.spec.ts
Normal file
24
core/src/components/checkbox/test/checkbox.spec.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { newSpecPage } from '@stencil/core/testing';
|
||||
|
||||
import { Checkbox } from '../checkbox';
|
||||
|
||||
describe('ion-checkbox: disabled', () => {
|
||||
it('clicking disabled checkbox should not toggle checked state', async () => {
|
||||
const page = await newSpecPage({
|
||||
components: [Checkbox],
|
||||
html: `
|
||||
<ion-checkbox disabled="true">Checkbox</ion-checkbox>
|
||||
`,
|
||||
});
|
||||
|
||||
const checkbox = page.body.querySelector('ion-checkbox');
|
||||
|
||||
expect(checkbox.checked).toBe(false);
|
||||
|
||||
checkbox.click();
|
||||
|
||||
await page.waitForChanges();
|
||||
|
||||
expect(checkbox.checked).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { ComponentInterface, EventEmitter } from '@stencil/core';
|
||||
import { Build, Component, Element, Event, Host, Listen, Method, Prop, forceUpdate, h, readTask } from '@stencil/core';
|
||||
import { componentOnReady } from '@utils/helpers';
|
||||
import { componentOnReady, hasLazyBuild } from '@utils/helpers';
|
||||
import { isPlatform } from '@utils/platform';
|
||||
import { isRTL } from '@utils/rtl';
|
||||
import { createColorClasses, hostContext } from '@utils/theme';
|
||||
@@ -34,6 +34,9 @@ export class Content implements ComponentInterface {
|
||||
private isMainContent = true;
|
||||
private resizeTimeout: ReturnType<typeof setTimeout> | null = null;
|
||||
|
||||
private tabsElement: HTMLElement | null = null;
|
||||
private tabsLoadCallback?: () => void;
|
||||
|
||||
// Detail is used in a hot loop in the scroll event, by allocating it here
|
||||
// V8 will be able to inline any read/write to it since it's a monomorphic class.
|
||||
// https://mrale.ph/blog/2015/01/11/whats-up-with-monomorphism.html
|
||||
@@ -115,15 +118,61 @@ export class Content implements ComponentInterface {
|
||||
|
||||
connectedCallback() {
|
||||
this.isMainContent = this.el.closest('ion-menu, ion-popover, ion-modal') === null;
|
||||
|
||||
/**
|
||||
* The fullscreen content offsets need to be
|
||||
* computed after the tab bar has loaded. Since
|
||||
* lazy evaluation means components are not hydrated
|
||||
* at the same time, we need to wait for the ionTabBarLoaded
|
||||
* event to fire. This does not impact dist-custom-elements
|
||||
* because there is no hydration there.
|
||||
*/
|
||||
if (hasLazyBuild(this.el)) {
|
||||
/**
|
||||
* We need to cache the reference to the tabs.
|
||||
* If just the content is unmounted then we won't
|
||||
* be able to query for the closest tabs on disconnectedCallback
|
||||
* since the content has been removed from the DOM tree.
|
||||
*/
|
||||
const closestTabs = (this.tabsElement = this.el.closest('ion-tabs'));
|
||||
if (closestTabs !== null) {
|
||||
/**
|
||||
* When adding and removing the event listener
|
||||
* we need to make sure we pass the same function reference
|
||||
* otherwise the event listener will not be removed properly.
|
||||
* We can't only pass `this.resize` because "this" in the function
|
||||
* context becomes a reference to IonTabs instead of IonContent.
|
||||
*
|
||||
* Additionally, we listen for ionTabBarLoaded on the IonTabs
|
||||
* instance rather than the IonTabBar instance. It's possible for
|
||||
* a tab bar to be conditionally rendered/mounted. Since ionTabBarLoaded
|
||||
* bubbles, we can catch any instances of child tab bars loading by listening
|
||||
* on IonTabs.
|
||||
*/
|
||||
this.tabsLoadCallback = () => this.resize();
|
||||
closestTabs.addEventListener('ionTabBarLoaded', this.tabsLoadCallback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
this.onScrollEnd();
|
||||
}
|
||||
|
||||
@Listen('appload', { target: 'window' })
|
||||
onAppLoad() {
|
||||
this.resize();
|
||||
if (hasLazyBuild(this.el)) {
|
||||
/**
|
||||
* The event listener and tabs caches need to
|
||||
* be cleared otherwise this will create a memory
|
||||
* leak where the IonTabs instance can never be
|
||||
* garbage collected.
|
||||
*/
|
||||
const { tabsElement, tabsLoadCallback } = this;
|
||||
if (tabsElement !== null && tabsLoadCallback !== undefined) {
|
||||
tabsElement.removeEventListener('ionTabBarLoaded', tabsLoadCallback);
|
||||
}
|
||||
|
||||
this.tabsElement = null;
|
||||
this.tabsLoadCallback = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -107,3 +107,28 @@
|
||||
.header-collapse-condense-inactive.header-collapse-condense ion-toolbar.in-toolbar ion-buttons.buttons-collapse {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
/**
|
||||
* The main header is only hidden once the collapsible large
|
||||
* title is configured. As a result, if the main header loads
|
||||
* before the collapsible large title is configured then the
|
||||
* main header will be visible briefly before being hidden
|
||||
* by the collapsible large title.
|
||||
*
|
||||
* The following selector ensures that any main header
|
||||
* on a page with a collapsible large title is hidden
|
||||
* before the collapsible large title is configured.
|
||||
* Once the collapsible large title is configured the main
|
||||
* header will have the ".header-collapse-main" class, and
|
||||
* this selector will no longer apply.
|
||||
*
|
||||
* The :has(...) part of the selector ensures a couple things:
|
||||
* 1. This will only apply within a page view since the content
|
||||
* must be a subsequent-sibling of the header (~ ion-content).
|
||||
* 2. This will only apply when that content has a collapse header (ion-header[collapse="condense"])
|
||||
*
|
||||
* We use opacity: 0 to avoid a layout shift.
|
||||
*/
|
||||
ion-header:not(.header-collapse-main):has(~ ion-content ion-header[collapse="condense"]) {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
@@ -40,6 +40,15 @@ export class Menu implements ComponentInterface, MenuI {
|
||||
private blocker = GESTURE_CONTROLLER.createBlocker({ disableScroll: true });
|
||||
private didLoad = false;
|
||||
|
||||
/**
|
||||
* Flag used to determine if an open/close
|
||||
* operation was cancelled. For example, if
|
||||
* an app calls "menu.open" then disables the menu
|
||||
* part way through the animation, then this would
|
||||
* be considered a cancelled operation.
|
||||
*/
|
||||
private operationCancelled = false;
|
||||
|
||||
isAnimating = false;
|
||||
width!: number;
|
||||
_isOpen = false;
|
||||
@@ -432,6 +441,17 @@ export class Menu implements ComponentInterface, MenuI {
|
||||
|
||||
await this.loadAnimation();
|
||||
await this.startAnimation(shouldOpen, animated);
|
||||
|
||||
/**
|
||||
* If the animation was cancelled then
|
||||
* return false because the operation
|
||||
* did not succeed.
|
||||
*/
|
||||
if (this.operationCancelled) {
|
||||
this.operationCancelled = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
this.afterAnimation(shouldOpen);
|
||||
|
||||
return true;
|
||||
@@ -472,18 +492,24 @@ export class Menu implements ComponentInterface, MenuI {
|
||||
const easingReverse = mode === 'ios' ? iosEasingReverse : mdEasingReverse;
|
||||
const ani = (this.animation as Animation)!
|
||||
.direction(isReversed ? 'reverse' : 'normal')
|
||||
.easing(isReversed ? easingReverse : easing)
|
||||
.onFinish(() => {
|
||||
if (ani.getDirection() === 'reverse') {
|
||||
ani.direction('normal');
|
||||
}
|
||||
});
|
||||
.easing(isReversed ? easingReverse : easing);
|
||||
|
||||
if (animated) {
|
||||
await ani.play();
|
||||
} else {
|
||||
ani.play({ sync: true });
|
||||
}
|
||||
|
||||
/**
|
||||
* We run this after the play invocation
|
||||
* instead of using ani.onFinish so that
|
||||
* multiple onFinish callbacks do not get
|
||||
* run if an animation is played, stopped,
|
||||
* and then played again.
|
||||
*/
|
||||
if (ani.getDirection() === 'reverse') {
|
||||
ani.direction('normal');
|
||||
}
|
||||
}
|
||||
|
||||
private _isActive() {
|
||||
@@ -643,8 +669,6 @@ export class Menu implements ComponentInterface, MenuI {
|
||||
}
|
||||
|
||||
private afterAnimation(isOpen: boolean) {
|
||||
assert(this.isAnimating, '_before() should be called while animating');
|
||||
|
||||
// keep opening/closing the menu disabled for a touch more yet
|
||||
// only add listeners/css if it's enabled and isOpen
|
||||
// and only remove listeners/css if it's not open
|
||||
@@ -713,10 +737,30 @@ export class Menu implements ComponentInterface, MenuI {
|
||||
this.gesture.enable(isActive && this.swipeGesture);
|
||||
}
|
||||
|
||||
// Close menu immediately
|
||||
if (!isActive && this._isOpen) {
|
||||
// close if this menu is open, and should not be enabled
|
||||
this.forceClosing();
|
||||
/**
|
||||
* If the menu is disabled but it is still open
|
||||
* then we should close the menu immediately.
|
||||
* Additionally, if the menu is in the process
|
||||
* of animating {open, close} and the menu is disabled
|
||||
* then it should still be closed immediately.
|
||||
*/
|
||||
if (!isActive) {
|
||||
/**
|
||||
* It is possible to disable the menu while
|
||||
* it is mid-animation. When this happens, we
|
||||
* need to set the operationCancelled flag
|
||||
* so that this._setOpen knows to return false
|
||||
* and not run the "afterAnimation" callback.
|
||||
*/
|
||||
if (this.isAnimating) {
|
||||
this.operationCancelled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the menu is disabled then we should
|
||||
* forcibly close the menu even if it is open.
|
||||
*/
|
||||
this.afterAnimation(false);
|
||||
}
|
||||
|
||||
if (doc?.contains(this.el)) {
|
||||
@@ -730,19 +774,6 @@ export class Menu implements ComponentInterface, MenuI {
|
||||
menuController._setActiveMenu(this);
|
||||
}
|
||||
}
|
||||
|
||||
assert(!this.isAnimating, 'can not be animating');
|
||||
}
|
||||
|
||||
private forceClosing() {
|
||||
assert(this._isOpen, 'menu cannot be closed');
|
||||
|
||||
this.isAnimating = true;
|
||||
|
||||
const ani = (this.animation as Animation)!.direction('reverse');
|
||||
ani.play({ sync: true });
|
||||
|
||||
this.afterAnimation(false);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
41
core/src/components/menu/test/disable/index.html
Normal file
41
core/src/components/menu/test/disable/index.html
Normal file
@@ -0,0 +1,41 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Menu - Disable</title>
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover"
|
||||
/>
|
||||
<link href="../../../../../css/ionic.bundle.css" rel="stylesheet" />
|
||||
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet" />
|
||||
<script src="../../../../../scripts/testing/scripts.js"></script>
|
||||
<script nomodule src="../../../../../dist/ionic/ionic.js"></script>
|
||||
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<ion-app>
|
||||
<ion-menu side="start" id="start-menu" menu-id="start-menu" content-id="main">
|
||||
<ion-header>
|
||||
<ion-toolbar color="primary">
|
||||
<ion-title>Menu</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content class="ion-padding"> Menu Content </ion-content>
|
||||
</ion-menu>
|
||||
|
||||
<div class="ion-page" id="main">
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="start">
|
||||
<ion-menu-button></ion-menu-button>
|
||||
</ion-buttons>
|
||||
<ion-title>Menu - Disable</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content class="ion-padding">Content</ion-content>
|
||||
</div>
|
||||
</ion-app>
|
||||
</body>
|
||||
</html>
|
||||
66
core/src/components/menu/test/disable/menu.e2e.ts
Normal file
66
core/src/components/menu/test/disable/menu.e2e.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
import { expect } from '@playwright/test';
|
||||
import { configs, test } from '@utils/test/playwright';
|
||||
|
||||
/**
|
||||
* This behavior does not vary across modes/directions
|
||||
*/
|
||||
configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
test.describe(title('menu: disable'), () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto(`/src/components/menu/test/disable`, config);
|
||||
});
|
||||
|
||||
test('should disable when menu is fully open', async ({ page }) => {
|
||||
const logs: string[] = [];
|
||||
|
||||
page.on('console', (msg) => {
|
||||
if (msg.type() === 'error') {
|
||||
logs.push(msg.text());
|
||||
}
|
||||
});
|
||||
|
||||
const menu = page.locator('ion-menu');
|
||||
|
||||
// Should be visible on initial presentation
|
||||
await menu.evaluate((el: HTMLIonMenuElement) => el.open());
|
||||
await expect(menu).toBeVisible();
|
||||
|
||||
// Disabling menu should hide it
|
||||
await menu.evaluate((el: HTMLIonMenuElement) => (el.disabled = true));
|
||||
await expect(menu).toBeHidden();
|
||||
|
||||
// Re-enabling menu and opening it show make it visible
|
||||
await menu.evaluate((el: HTMLIonMenuElement) => (el.disabled = false));
|
||||
await menu.evaluate((el: HTMLIonMenuElement) => el.open());
|
||||
await expect(menu).toBeVisible();
|
||||
|
||||
expect(logs.length).toBe(0);
|
||||
});
|
||||
|
||||
test('should disable when menu is animating', async ({ page }) => {
|
||||
const logs: string[] = [];
|
||||
|
||||
page.on('console', (msg) => {
|
||||
if (msg.type() === 'error') {
|
||||
logs.push(msg.text());
|
||||
}
|
||||
});
|
||||
|
||||
const menu = page.locator('ion-menu');
|
||||
|
||||
// Opening and quickly disabling menu should hide it
|
||||
menu.evaluate((el: HTMLIonMenuElement) => {
|
||||
el.open();
|
||||
setTimeout(() => (el.disabled = true), 0);
|
||||
});
|
||||
await expect(menu).toBeHidden();
|
||||
|
||||
// Re-enabling menu and opening it show make it visible
|
||||
await menu.evaluate((el: HTMLIonMenuElement) => (el.disabled = false));
|
||||
await menu.evaluate((el: HTMLIonMenuElement) => el.open());
|
||||
await expect(menu).toBeVisible();
|
||||
|
||||
expect(logs.length).toBe(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -6,6 +6,5 @@
|
||||
position: absolute;
|
||||
|
||||
contain: layout size style;
|
||||
overflow: hidden;
|
||||
z-index: $z-index-page-container;
|
||||
}
|
||||
|
||||
@@ -414,9 +414,11 @@ export class PickerColumnInternal implements ComponentInterface {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { items, color, isActive, numericInput } = this;
|
||||
const { items, color, isActive, numericInput, value } = this;
|
||||
const mode = getIonMode(this);
|
||||
|
||||
const activeItem = items.find(item => item.value === value);
|
||||
|
||||
/**
|
||||
* exportparts is needed so ion-datetime can expose the parts
|
||||
* from two layers of shadow nesting. If this causes problems,
|
||||
@@ -425,6 +427,11 @@ export class PickerColumnInternal implements ComponentInterface {
|
||||
*/
|
||||
return (
|
||||
<Host
|
||||
role="spinbutton"
|
||||
aria-valuemin="0"
|
||||
aria-valuemax="0"
|
||||
aria-valuenow={activeItem ? activeItem.value : null}
|
||||
aria-valuetext={activeItem ? activeItem.text : null}
|
||||
exportparts={`${PICKER_ITEM_PART}, ${PICKER_ITEM_ACTIVE_PART}`}
|
||||
tabindex={0}
|
||||
class={createColorClasses(color, {
|
||||
|
||||
@@ -113,7 +113,7 @@ export class RadioGroup implements ComponentInterface {
|
||||
* using the `name` attribute.
|
||||
*/
|
||||
const selectedRadio = ev.target && (ev.target as HTMLElement).closest('ion-radio');
|
||||
if (selectedRadio) {
|
||||
if (selectedRadio && selectedRadio.disabled === false) {
|
||||
const currentValue = this.value;
|
||||
const newValue = selectedRadio.value;
|
||||
if (newValue !== currentValue) {
|
||||
|
||||
@@ -200,7 +200,11 @@ export class Radio implements ComponentInterface {
|
||||
};
|
||||
|
||||
private onClick = () => {
|
||||
const { radioGroup, checked } = this;
|
||||
const { radioGroup, checked, disabled } = this;
|
||||
|
||||
if (disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* The legacy control uses a native input inside
|
||||
|
||||
@@ -31,3 +31,27 @@ describe('ion-radio', () => {
|
||||
expect(radio.classList.contains('radio-checked')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('ion-radio: disabled', () => {
|
||||
it('clicking disabled radio should not set checked state', async () => {
|
||||
const page = await newSpecPage({
|
||||
components: [Radio, RadioGroup],
|
||||
html: `
|
||||
<ion-radio-group>
|
||||
<ion-radio disabled="true" value="a">Radio</ion-radio>
|
||||
</ion-radio-group>
|
||||
`,
|
||||
});
|
||||
|
||||
const radio = page.body.querySelector('ion-radio');
|
||||
const radioGroup = page.body.querySelector('ion-radio-group');
|
||||
|
||||
expect(radioGroup.value).toBe(undefined);
|
||||
|
||||
radio.click();
|
||||
|
||||
await page.waitForChanges();
|
||||
|
||||
expect(radioGroup.value).toBe(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -6,6 +6,5 @@
|
||||
position: absolute;
|
||||
|
||||
contain: layout size style;
|
||||
overflow: hidden;
|
||||
z-index: $z-index-page-container;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { Component, Element, Event, Method, Prop, Watch, h } from '@stencil/core
|
||||
import { getTimeGivenProgression } from '@utils/animation/cubic-bezier';
|
||||
import { attachComponent, detachComponent } from '@utils/framework-delegate';
|
||||
import { shallowEqualStringMap, hasLazyBuild } from '@utils/helpers';
|
||||
import { createLockController } from '@utils/lock-controller';
|
||||
import { transition } from '@utils/transition';
|
||||
|
||||
import { config } from '../../global/config';
|
||||
@@ -24,11 +25,11 @@ import type { RouteID, RouterDirection, RouteWrite, NavOutlet } from '../router/
|
||||
shadow: true,
|
||||
})
|
||||
export class RouterOutlet implements ComponentInterface, NavOutlet {
|
||||
private readonly lockController = createLockController();
|
||||
private activeEl: HTMLElement | undefined;
|
||||
// TODO(FW-2832): types
|
||||
private activeComponent: any;
|
||||
private activeParams: any;
|
||||
private waitPromise?: Promise<void>;
|
||||
private gesture?: Gesture;
|
||||
private ani?: Animation;
|
||||
private gestureOrAnimationInProgress = false;
|
||||
@@ -140,7 +141,7 @@ export class RouterOutlet implements ComponentInterface, NavOutlet {
|
||||
leavingEl: HTMLElement | undefined,
|
||||
opts?: RouterOutletOptions
|
||||
): Promise<boolean> {
|
||||
const unlock = await this.lock();
|
||||
const unlock = await this.lockController.lock();
|
||||
let changed = false;
|
||||
try {
|
||||
changed = await this.transition(enteringEl, leavingEl, opts);
|
||||
@@ -285,18 +286,6 @@ export class RouterOutlet implements ComponentInterface, NavOutlet {
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: FW-5048 - Remove this code in favor of using lock controller from utils
|
||||
private async lock() {
|
||||
const p = this.waitPromise;
|
||||
let resolve!: () => void;
|
||||
this.waitPromise = new Promise((r) => (resolve = r));
|
||||
|
||||
if (p !== undefined) {
|
||||
await p;
|
||||
}
|
||||
return resolve;
|
||||
}
|
||||
|
||||
render() {
|
||||
return <slot></slot>;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { ComponentInterface, EventEmitter } from '@stencil/core';
|
||||
import { Component, Element, Event, Host, Listen, Prop, State, Watch, h, writeTask } from '@stencil/core';
|
||||
import type { Gesture, GestureDetail } from '@utils/gesture';
|
||||
import { raf } from '@utils/helpers';
|
||||
import { isRTL } from '@utils/rtl';
|
||||
import { createColorClasses, hostContext } from '@utils/theme';
|
||||
|
||||
@@ -83,31 +84,7 @@ export class Segment implements ComponentInterface {
|
||||
* Used by `ion-segment-button` to determine if the button should be checked.
|
||||
*/
|
||||
this.ionSelect.emit({ value });
|
||||
|
||||
if (this.scrollable) {
|
||||
const buttons = this.getButtons();
|
||||
const activeButton = buttons.find((button) => button.value === value);
|
||||
if (activeButton !== undefined) {
|
||||
/**
|
||||
* Scrollable segment buttons should be
|
||||
* centered within the view including
|
||||
* buttons that are partially offscreen.
|
||||
*/
|
||||
activeButton.scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
inline: 'center',
|
||||
|
||||
/**
|
||||
* Segment should scroll on the
|
||||
* horizontal axis. `block: 'nearest'`
|
||||
* ensures that the vertical axis
|
||||
* does not scroll if the segment
|
||||
* as a whole is already in view.
|
||||
*/
|
||||
block: 'nearest',
|
||||
});
|
||||
}
|
||||
}
|
||||
this.scrollActiveButtonIntoView();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -163,6 +140,14 @@ export class Segment implements ComponentInterface {
|
||||
async componentDidLoad() {
|
||||
this.setCheckedClasses();
|
||||
|
||||
/**
|
||||
* We need to wait for the buttons to all be rendered
|
||||
* before we can scroll.
|
||||
*/
|
||||
raf(() => {
|
||||
this.scrollActiveButtonIntoView();
|
||||
});
|
||||
|
||||
this.gesture = (await import('../../utils/gesture')).createGesture({
|
||||
el: this.el,
|
||||
gestureName: 'segment',
|
||||
@@ -320,6 +305,35 @@ export class Segment implements ComponentInterface {
|
||||
}
|
||||
}
|
||||
|
||||
private scrollActiveButtonIntoView() {
|
||||
const { scrollable, value } = this;
|
||||
|
||||
if (scrollable) {
|
||||
const buttons = this.getButtons();
|
||||
const activeButton = buttons.find((button) => button.value === value);
|
||||
if (activeButton !== undefined) {
|
||||
/**
|
||||
* Scrollable segment buttons should be
|
||||
* centered within the view including
|
||||
* buttons that are partially offscreen.
|
||||
*/
|
||||
activeButton.scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
inline: 'center',
|
||||
|
||||
/**
|
||||
* Segment should scroll on the
|
||||
* horizontal axis. `block: 'nearest'`
|
||||
* ensures that the vertical axis
|
||||
* does not scroll if the segment
|
||||
* as a whole is already in view.
|
||||
*/
|
||||
block: 'nearest',
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private setNextIndex(detail: GestureDetail, isEnd = false) {
|
||||
const rtl = isRTL(this.el);
|
||||
const activated = this.activated;
|
||||
|
||||
@@ -2,7 +2,7 @@ import { expect } from '@playwright/test';
|
||||
import { configs, test } from '@utils/test/playwright';
|
||||
|
||||
configs().forEach(({ title, screenshot, config }) => {
|
||||
test.describe(title('segment: scrollable'), () => {
|
||||
test.describe(title('segment: scrollable (rendering)'), () => {
|
||||
test('should not have visual regressions', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
@@ -45,3 +45,47 @@ configs().forEach(({ title, screenshot, config }) => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
test.describe(title('segment: scrollable (functionality)'), () => {
|
||||
test('should scroll active button into view when value is already set', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-segment scrollable="true" value="8">
|
||||
<ion-segment-button value="1">
|
||||
<ion-label>First</ion-label>
|
||||
</ion-segment-button>
|
||||
<ion-segment-button value="2">
|
||||
<ion-label>Second</ion-label>
|
||||
</ion-segment-button>
|
||||
<ion-segment-button value="3">
|
||||
<ion-label>Third</ion-label>
|
||||
</ion-segment-button>
|
||||
<ion-segment-button value="4">
|
||||
<ion-label>Fourth</ion-label>
|
||||
</ion-segment-button>
|
||||
<ion-segment-button value="5">
|
||||
<ion-label>Fifth</ion-label>
|
||||
</ion-segment-button>
|
||||
<ion-segment-button value="6">
|
||||
<ion-label>Sixth</ion-label>
|
||||
</ion-segment-button>
|
||||
<ion-segment-button value="7">
|
||||
<ion-label>Seventh</ion-label>
|
||||
</ion-segment-button>
|
||||
<ion-segment-button id="activeButton" value="8">
|
||||
<ion-label>Eighth</ion-label>
|
||||
</ion-segment-button>
|
||||
<ion-segment-button value="9">
|
||||
<ion-label>Ninth</ion-label>
|
||||
</ion-segment-button>
|
||||
</ion-segment>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
const activeButton = page.locator('#activeButton');
|
||||
await expect(activeButton).toBeInViewport();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -316,29 +316,46 @@ export class Select implements ComponentInterface {
|
||||
|
||||
// focus selected option for popovers
|
||||
if (this.interface === 'popover') {
|
||||
let indexOfSelected = this.childOpts.map((o) => o.value).indexOf(this.value);
|
||||
indexOfSelected = indexOfSelected > -1 ? indexOfSelected : 0; // default to first option if nothing selected
|
||||
const selectedItem = overlay.querySelector<HTMLElement>(
|
||||
`.select-interface-option:nth-child(${indexOfSelected + 1})`
|
||||
);
|
||||
const indexOfSelected = this.childOpts.map((o) => o.value).indexOf(this.value);
|
||||
|
||||
if (selectedItem) {
|
||||
focusElement(selectedItem);
|
||||
if (indexOfSelected > -1) {
|
||||
const selectedItem = overlay.querySelector<HTMLElement>(
|
||||
`.select-interface-option:nth-child(${indexOfSelected + 1})`
|
||||
);
|
||||
|
||||
if (selectedItem) {
|
||||
focusElement(selectedItem);
|
||||
|
||||
/**
|
||||
* Browsers such as Firefox do not
|
||||
* correctly delegate focus when manually
|
||||
* focusing an element with delegatesFocus.
|
||||
* We work around this by manually focusing
|
||||
* the interactive element.
|
||||
* ion-radio and ion-checkbox are the only
|
||||
* elements that ion-select-popover uses, so
|
||||
* we only need to worry about those two components
|
||||
* when focusing.
|
||||
*/
|
||||
const interactiveEl = selectedItem.querySelector<HTMLElement>('ion-radio, ion-checkbox');
|
||||
if (interactiveEl) {
|
||||
interactiveEl.focus();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/**
|
||||
* Browsers such as Firefox do not
|
||||
* correctly delegate focus when manually
|
||||
* focusing an element with delegatesFocus.
|
||||
* We work around this by manually focusing
|
||||
* the interactive element.
|
||||
* ion-radio and ion-checkbox are the only
|
||||
* elements that ion-select-popover uses, so
|
||||
* we only need to worry about those two components
|
||||
* when focusing.
|
||||
* If no value is set then focus the first enabled option.
|
||||
*/
|
||||
const interactiveEl = selectedItem.querySelector<HTMLElement>('ion-radio, ion-checkbox');
|
||||
if (interactiveEl) {
|
||||
interactiveEl.focus();
|
||||
const firstEnabledOption = overlay.querySelector<HTMLElement>(
|
||||
'ion-radio:not(.radio-disabled), ion-checkbox:not(.checkbox-disabled)'
|
||||
);
|
||||
if (firstEnabledOption) {
|
||||
focusElement(firstEnabledOption.closest('ion-item')!);
|
||||
|
||||
/**
|
||||
* Focus the option for the same reason as we do above.
|
||||
*/
|
||||
firstEnabledOption.focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
36
core/src/components/select/test/disabled/select.e2e.ts
Normal file
36
core/src/components/select/test/disabled/select.e2e.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { expect } from '@playwright/test';
|
||||
import { configs, test } from '@utils/test/playwright';
|
||||
|
||||
configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
test.describe(title('select: disabled options'), () => {
|
||||
test('should not focus a disabled option when no value is set', async ({ page, skip }) => {
|
||||
// TODO (FW-2979)
|
||||
skip.browser('webkit', 'Safari 16 only allows text fields and pop-up menus to be focused.');
|
||||
|
||||
test.info().annotations.push({
|
||||
type: 'issue',
|
||||
description: 'https://github.com/ionic-team/ionic-framework/issues/28284',
|
||||
});
|
||||
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-select interface="popover">
|
||||
<ion-select-option value="a" disabled="true">A</ion-select-option>
|
||||
<ion-select-option value="b">B</ion-select-option>
|
||||
</ion-select>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
const select = page.locator('ion-select');
|
||||
const popover = page.locator('ion-popover');
|
||||
const ionPopoverDidPresent = await page.spyOnEvent('ionPopoverDidPresent');
|
||||
|
||||
await select.click();
|
||||
await ionPopoverDidPresent.next();
|
||||
|
||||
const popoverOption = popover.locator('.select-interface-option:nth-of-type(2) ion-radio');
|
||||
await expect(popoverOption).toBeFocused();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -57,6 +57,14 @@ export class TabBar implements ComponentInterface {
|
||||
/** @internal */
|
||||
@Event() ionTabBarChanged!: EventEmitter<TabBarChangedEventDetail>;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* This event is used in IonContent to correctly
|
||||
* calculate the fullscreen content offsets
|
||||
* when IonTabBar is used.
|
||||
*/
|
||||
@Event() ionTabBarLoaded!: EventEmitter<void>;
|
||||
|
||||
componentWillLoad() {
|
||||
this.selectedTabChanged();
|
||||
}
|
||||
@@ -82,6 +90,10 @@ export class TabBar implements ComponentInterface {
|
||||
}
|
||||
}
|
||||
|
||||
componentDidLoad() {
|
||||
this.ionTabBarLoaded.emit();
|
||||
}
|
||||
|
||||
render() {
|
||||
const { color, translucent, keyboardVisible } = this;
|
||||
const mode = getIonMode(this);
|
||||
|
||||
@@ -39,5 +39,40 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, screenshot, c
|
||||
|
||||
await expect(tabBar).toHaveScreenshot(screenshot(`tab-bar-translucent`));
|
||||
});
|
||||
test('should render translucent tab bar even when wrapped in a page container', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<style>
|
||||
ion-content {
|
||||
--background: linear-gradient(to right, orange, yellow, green, cyan, blue, violet);
|
||||
}
|
||||
</style>
|
||||
<ion-tabs>
|
||||
<div class="ion-page">
|
||||
<ion-content fullscreen="true">My Content</ion-content>
|
||||
</div>
|
||||
<ion-tab-bar slot="bottom" translucent="true" selected-tab="1">
|
||||
<ion-tab-button tab="1">
|
||||
<ion-label>Recents</ion-label>
|
||||
</ion-tab-button>
|
||||
|
||||
<ion-tab-button tab="2">
|
||||
<ion-label>Favorites</ion-label>
|
||||
<ion-badge>23</ion-badge>
|
||||
</ion-tab-button>
|
||||
|
||||
<ion-tab-button tab="3">
|
||||
<ion-label>Settings</ion-label>
|
||||
</ion-tab-button>
|
||||
</ion-tab-bar>
|
||||
</ion-tabs>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
const tabBar = page.locator('ion-tab-bar');
|
||||
|
||||
await expect(tabBar).toHaveScreenshot(screenshot(`tab-bar-translucent-container`));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 5.2 KiB |
@@ -41,3 +41,24 @@ describe('toggle', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('ion-toggle: disabled', () => {
|
||||
it('clicking disabled toggle should not toggle checked state', async () => {
|
||||
const page = await newSpecPage({
|
||||
components: [Toggle],
|
||||
html: `
|
||||
<ion-toggle disabled="true">Toggle</ion-toggle>
|
||||
`,
|
||||
});
|
||||
|
||||
const toggle = page.body.querySelector('ion-toggle');
|
||||
|
||||
expect(toggle.checked).toBe(false);
|
||||
|
||||
toggle.click();
|
||||
|
||||
await page.waitForChanges();
|
||||
|
||||
expect(toggle.checked).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -259,6 +259,10 @@ export class Toggle implements ComponentInterface {
|
||||
}
|
||||
|
||||
private onClick = (ev: MouseEvent) => {
|
||||
if (this.disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
ev.preventDefault();
|
||||
|
||||
if (this.lastDrag + 300 < Date.now()) {
|
||||
|
||||
@@ -156,7 +156,6 @@ html.ios ion-modal.modal-card .ion-page {
|
||||
justify-content: space-between;
|
||||
|
||||
contain: layout size style;
|
||||
overflow: hidden;
|
||||
z-index: $z-index-page-container;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,8 @@ interface AnimationOnFinishCallback {
|
||||
o?: AnimationCallbackOptions;
|
||||
}
|
||||
|
||||
type AnimationOnStopCallback = AnimationOnFinishCallback;
|
||||
|
||||
export const createAnimation = (animationId?: string): Animation => {
|
||||
let _delay: number | undefined;
|
||||
let _duration: number | undefined;
|
||||
@@ -63,6 +65,7 @@ export const createAnimation = (animationId?: string): Animation => {
|
||||
const id: string | undefined = animationId;
|
||||
const onFinishCallbacks: AnimationOnFinishCallback[] = [];
|
||||
const onFinishOneTimeCallbacks: AnimationOnFinishCallback[] = [];
|
||||
const onStopOneTimeCallbacks: AnimationOnStopCallback[] = [];
|
||||
const elements: HTMLElement[] = [];
|
||||
const childAnimations: Animation[] = [];
|
||||
const stylesheets: HTMLElement[] = [];
|
||||
@@ -134,6 +137,35 @@ export const createAnimation = (animationId?: string): Animation => {
|
||||
return numAnimationsRunning !== 0 && !paused;
|
||||
};
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* Remove a callback from a chosen callback array
|
||||
* @param callbackToRemove: A reference to the callback that should be removed
|
||||
* @param callbackObjects: An array of callbacks that callbackToRemove should be removed from.
|
||||
*/
|
||||
const clearCallback = (
|
||||
callbackToRemove: AnimationLifecycle,
|
||||
callbackObjects: AnimationOnFinishCallback[] | AnimationOnStopCallback[]
|
||||
) => {
|
||||
const index = callbackObjects.findIndex((callbackObject) => callbackObject.c === callbackToRemove);
|
||||
|
||||
if (index > -1) {
|
||||
callbackObjects.splice(index, 1);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* Add a callback to be fired when an animation is stopped/cancelled.
|
||||
* @param callback: A reference to the callback that should be fired
|
||||
* @param opts: Any options associated with this particular callback
|
||||
*/
|
||||
const onStop = (callback: AnimationLifecycle, opts?: AnimationCallbackOptions) => {
|
||||
onStopOneTimeCallbacks.push({ c: callback, o: opts });
|
||||
|
||||
return ani;
|
||||
};
|
||||
|
||||
const onFinish = (callback: AnimationLifecycle, opts?: AnimationCallbackOptions) => {
|
||||
const callbacks = opts?.oneTimeCallback ? onFinishOneTimeCallbacks : onFinishCallbacks;
|
||||
callbacks.push({ c: callback, o: opts });
|
||||
@@ -953,7 +985,34 @@ export const createAnimation = (animationId?: string): Animation => {
|
||||
shouldCalculateNumAnimations = false;
|
||||
}
|
||||
|
||||
onFinish(() => resolve(), { oneTimeCallback: true });
|
||||
/**
|
||||
* When one of these callbacks fires we
|
||||
* need to clear the other's callback otherwise
|
||||
* you can potentially get these callbacks
|
||||
* firing multiple times if the play method
|
||||
* is subsequently called.
|
||||
* Example:
|
||||
* animation.play() (onStop and onFinish callbacks are registered)
|
||||
* animation.stop() (onStop callback is fired, onFinish is not)
|
||||
* animation.play() (onStop and onFinish callbacks are registered)
|
||||
* Total onStop callbacks: 1
|
||||
* Total onFinish callbacks: 2
|
||||
*/
|
||||
const onStopCallback = () => {
|
||||
clearCallback(onFinishCallback, onFinishOneTimeCallbacks);
|
||||
resolve();
|
||||
};
|
||||
const onFinishCallback = () => {
|
||||
clearCallback(onStopCallback, onStopOneTimeCallbacks);
|
||||
resolve();
|
||||
};
|
||||
|
||||
/**
|
||||
* The play method resolves when an animation
|
||||
* run either finishes or is cancelled.
|
||||
*/
|
||||
onFinish(onFinishCallback, { oneTimeCallback: true });
|
||||
onStop(onStopCallback, { oneTimeCallback: true });
|
||||
|
||||
childAnimations.forEach((animation) => {
|
||||
animation.play();
|
||||
@@ -969,6 +1028,14 @@ export const createAnimation = (animationId?: string): Animation => {
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Stops an animation and resets it state to the
|
||||
* beginning. This does not fire any onFinish
|
||||
* callbacks because the animation did not finish.
|
||||
* However, since the animation was not destroyed
|
||||
* (i.e. the animation could run again) we do not
|
||||
* clear the onFinish callbacks.
|
||||
*/
|
||||
const stop = () => {
|
||||
childAnimations.forEach((animation) => {
|
||||
animation.stop();
|
||||
@@ -980,6 +1047,9 @@ export const createAnimation = (animationId?: string): Animation => {
|
||||
}
|
||||
|
||||
resetFlags();
|
||||
|
||||
onStopOneTimeCallbacks.forEach((onStopCallback) => onStopCallback.c(0, ani));
|
||||
onStopOneTimeCallbacks.length = 0;
|
||||
};
|
||||
|
||||
const from = (property: string, value: any) => {
|
||||
|
||||
@@ -4,6 +4,24 @@ import { processKeyframes } from '../animation-utils';
|
||||
import { getTimeGivenProgression } from '../cubic-bezier';
|
||||
|
||||
describe('Animation Class', () => {
|
||||
describe('play()', () => {
|
||||
it('should resolve when the animation is cancelled', async () => {
|
||||
// Tell Jest to expect 1 assertion for async code
|
||||
expect.assertions(1);
|
||||
const el = document.createElement('div');
|
||||
const animation = createAnimation()
|
||||
.addElement(el)
|
||||
.fromTo('transform', 'translateX(0px)', 'translateX(100px)')
|
||||
.duration(100000);
|
||||
|
||||
const animationPromise = animation.play();
|
||||
|
||||
animation.stop();
|
||||
|
||||
// Expect that the promise resolves and returns undefined
|
||||
expect(animationPromise).resolves.toEqual(undefined);
|
||||
});
|
||||
});
|
||||
describe('isRunning()', () => {
|
||||
let animation: Animation;
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -79,7 +79,11 @@ export const createSwipeBackGesture = (
|
||||
return createGesture({
|
||||
el,
|
||||
gestureName: 'goback-swipe',
|
||||
gesturePriority: 40,
|
||||
/**
|
||||
* Swipe to go back should have priority over other horizontal swipe
|
||||
* gestures. These gestures have a priority of 100 which is why 101 was chosen here.
|
||||
*/
|
||||
gesturePriority: 101,
|
||||
threshold: 10,
|
||||
canStart,
|
||||
onStart: onStartHandler,
|
||||
|
||||
28
packages/angular-server/package-lock.json
generated
28
packages/angular-server/package-lock.json
generated
@@ -1060,19 +1060,19 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@ionic/core": {
|
||||
"version": "7.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.4.2.tgz",
|
||||
"integrity": "sha512-ePuP+SxS6HY/nos267dBdAvL0kth1FYUWs8Y+DSM+FFTeRdEbvOsa2JeQCY7gCt/Ep9e7lSND95qfkX23pGNDA==",
|
||||
"version": "7.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.4.3.tgz",
|
||||
"integrity": "sha512-JPQLGojKnI/L0UBVshRv86DOSDj61rJRFYQImU4IcgP/rw5ckxwt3iZ5NtdJl0eEDwu91n68aGJdU+TFJjMJgQ==",
|
||||
"dependencies": {
|
||||
"@stencil/core": "^4.3.0",
|
||||
"@stencil/core": "^4.4.0",
|
||||
"ionicons": "7.1.0",
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@ionic/core/node_modules/@stencil/core": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.3.0.tgz",
|
||||
"integrity": "sha512-WYjftKg5fuqO7mf3nTl1aCRurkeMmfEF38WcBG4VLF6UPQ+MA76/koedGR2LGhATGByx+pbxR4iRxAr2Bspc9A==",
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.4.0.tgz",
|
||||
"integrity": "sha512-YlLyCqGBsMEuZb3XTO/STT0TX9eSwjoVhCJgtjVfQOF+ebIMVlojTh40CmDveWiWbth687cbr6S2heeussV8Sg==",
|
||||
"bin": {
|
||||
"stencil": "bin/stencil"
|
||||
},
|
||||
@@ -7342,19 +7342,19 @@
|
||||
"dev": true
|
||||
},
|
||||
"@ionic/core": {
|
||||
"version": "7.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.4.2.tgz",
|
||||
"integrity": "sha512-ePuP+SxS6HY/nos267dBdAvL0kth1FYUWs8Y+DSM+FFTeRdEbvOsa2JeQCY7gCt/Ep9e7lSND95qfkX23pGNDA==",
|
||||
"version": "7.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.4.3.tgz",
|
||||
"integrity": "sha512-JPQLGojKnI/L0UBVshRv86DOSDj61rJRFYQImU4IcgP/rw5ckxwt3iZ5NtdJl0eEDwu91n68aGJdU+TFJjMJgQ==",
|
||||
"requires": {
|
||||
"@stencil/core": "^4.3.0",
|
||||
"@stencil/core": "^4.4.0",
|
||||
"ionicons": "7.1.0",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@stencil/core": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.3.0.tgz",
|
||||
"integrity": "sha512-WYjftKg5fuqO7mf3nTl1aCRurkeMmfEF38WcBG4VLF6UPQ+MA76/koedGR2LGhATGByx+pbxR4iRxAr2Bspc9A=="
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.4.0.tgz",
|
||||
"integrity": "sha512-YlLyCqGBsMEuZb3XTO/STT0TX9eSwjoVhCJgtjVfQOF+ebIMVlojTh40CmDveWiWbth687cbr6S2heeussV8Sg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
28
packages/angular/package-lock.json
generated
28
packages/angular/package-lock.json
generated
@@ -1227,19 +1227,19 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@ionic/core": {
|
||||
"version": "7.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.4.2.tgz",
|
||||
"integrity": "sha512-ePuP+SxS6HY/nos267dBdAvL0kth1FYUWs8Y+DSM+FFTeRdEbvOsa2JeQCY7gCt/Ep9e7lSND95qfkX23pGNDA==",
|
||||
"version": "7.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.4.3.tgz",
|
||||
"integrity": "sha512-JPQLGojKnI/L0UBVshRv86DOSDj61rJRFYQImU4IcgP/rw5ckxwt3iZ5NtdJl0eEDwu91n68aGJdU+TFJjMJgQ==",
|
||||
"dependencies": {
|
||||
"@stencil/core": "^4.3.0",
|
||||
"@stencil/core": "^4.4.0",
|
||||
"ionicons": "7.1.0",
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@ionic/core/node_modules/@stencil/core": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.3.0.tgz",
|
||||
"integrity": "sha512-WYjftKg5fuqO7mf3nTl1aCRurkeMmfEF38WcBG4VLF6UPQ+MA76/koedGR2LGhATGByx+pbxR4iRxAr2Bspc9A==",
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.4.0.tgz",
|
||||
"integrity": "sha512-YlLyCqGBsMEuZb3XTO/STT0TX9eSwjoVhCJgtjVfQOF+ebIMVlojTh40CmDveWiWbth687cbr6S2heeussV8Sg==",
|
||||
"bin": {
|
||||
"stencil": "bin/stencil"
|
||||
},
|
||||
@@ -8104,19 +8104,19 @@
|
||||
"dev": true
|
||||
},
|
||||
"@ionic/core": {
|
||||
"version": "7.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.4.2.tgz",
|
||||
"integrity": "sha512-ePuP+SxS6HY/nos267dBdAvL0kth1FYUWs8Y+DSM+FFTeRdEbvOsa2JeQCY7gCt/Ep9e7lSND95qfkX23pGNDA==",
|
||||
"version": "7.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.4.3.tgz",
|
||||
"integrity": "sha512-JPQLGojKnI/L0UBVshRv86DOSDj61rJRFYQImU4IcgP/rw5ckxwt3iZ5NtdJl0eEDwu91n68aGJdU+TFJjMJgQ==",
|
||||
"requires": {
|
||||
"@stencil/core": "^4.3.0",
|
||||
"@stencil/core": "^4.4.0",
|
||||
"ionicons": "7.1.0",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@stencil/core": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.3.0.tgz",
|
||||
"integrity": "sha512-WYjftKg5fuqO7mf3nTl1aCRurkeMmfEF38WcBG4VLF6UPQ+MA76/koedGR2LGhATGByx+pbxR4iRxAr2Bspc9A=="
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.4.0.tgz",
|
||||
"integrity": "sha512-YlLyCqGBsMEuZb3XTO/STT0TX9eSwjoVhCJgtjVfQOF+ebIMVlojTh40CmDveWiWbth687cbr6S2heeussV8Sg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
44
packages/react-router/package-lock.json
generated
44
packages/react-router/package-lock.json
generated
@@ -205,11 +205,11 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@ionic/core": {
|
||||
"version": "7.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.4.2.tgz",
|
||||
"integrity": "sha512-ePuP+SxS6HY/nos267dBdAvL0kth1FYUWs8Y+DSM+FFTeRdEbvOsa2JeQCY7gCt/Ep9e7lSND95qfkX23pGNDA==",
|
||||
"version": "7.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.4.3.tgz",
|
||||
"integrity": "sha512-JPQLGojKnI/L0UBVshRv86DOSDj61rJRFYQImU4IcgP/rw5ckxwt3iZ5NtdJl0eEDwu91n68aGJdU+TFJjMJgQ==",
|
||||
"dependencies": {
|
||||
"@stencil/core": "^4.3.0",
|
||||
"@stencil/core": "^4.4.0",
|
||||
"ionicons": "7.1.0",
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
@@ -401,11 +401,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@ionic/react": {
|
||||
"version": "7.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/react/-/react-7.4.2.tgz",
|
||||
"integrity": "sha512-lU6rVunrEQhpgC4ftEzqNC30c8U2PQTQivzwDSkd2y/WsJSCzYyG/+ZHhACSWfa4dbGZizOHdFCWsnAjZjDJFw==",
|
||||
"version": "7.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/react/-/react-7.4.3.tgz",
|
||||
"integrity": "sha512-j33s8CFe3Cu3AQtIlZdI/W4+e5hDzjRcX6uwqRrizcMQS66Sj9Ik9RN5v3jV/9R8MHLElXZof/AhofNEhe7BTw==",
|
||||
"dependencies": {
|
||||
"@ionic/core": "7.4.2",
|
||||
"@ionic/core": "7.4.3",
|
||||
"ionicons": "^7.0.0",
|
||||
"tslib": "*"
|
||||
},
|
||||
@@ -486,9 +486,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@stencil/core": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.3.0.tgz",
|
||||
"integrity": "sha512-WYjftKg5fuqO7mf3nTl1aCRurkeMmfEF38WcBG4VLF6UPQ+MA76/koedGR2LGhATGByx+pbxR4iRxAr2Bspc9A==",
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.4.0.tgz",
|
||||
"integrity": "sha512-YlLyCqGBsMEuZb3XTO/STT0TX9eSwjoVhCJgtjVfQOF+ebIMVlojTh40CmDveWiWbth687cbr6S2heeussV8Sg==",
|
||||
"bin": {
|
||||
"stencil": "bin/stencil"
|
||||
},
|
||||
@@ -3663,11 +3663,11 @@
|
||||
"dev": true
|
||||
},
|
||||
"@ionic/core": {
|
||||
"version": "7.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.4.2.tgz",
|
||||
"integrity": "sha512-ePuP+SxS6HY/nos267dBdAvL0kth1FYUWs8Y+DSM+FFTeRdEbvOsa2JeQCY7gCt/Ep9e7lSND95qfkX23pGNDA==",
|
||||
"version": "7.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.4.3.tgz",
|
||||
"integrity": "sha512-JPQLGojKnI/L0UBVshRv86DOSDj61rJRFYQImU4IcgP/rw5ckxwt3iZ5NtdJl0eEDwu91n68aGJdU+TFJjMJgQ==",
|
||||
"requires": {
|
||||
"@stencil/core": "^4.3.0",
|
||||
"@stencil/core": "^4.4.0",
|
||||
"ionicons": "7.1.0",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
@@ -3786,11 +3786,11 @@
|
||||
"requires": {}
|
||||
},
|
||||
"@ionic/react": {
|
||||
"version": "7.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/react/-/react-7.4.2.tgz",
|
||||
"integrity": "sha512-lU6rVunrEQhpgC4ftEzqNC30c8U2PQTQivzwDSkd2y/WsJSCzYyG/+ZHhACSWfa4dbGZizOHdFCWsnAjZjDJFw==",
|
||||
"version": "7.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/react/-/react-7.4.3.tgz",
|
||||
"integrity": "sha512-j33s8CFe3Cu3AQtIlZdI/W4+e5hDzjRcX6uwqRrizcMQS66Sj9Ik9RN5v3jV/9R8MHLElXZof/AhofNEhe7BTw==",
|
||||
"requires": {
|
||||
"@ionic/core": "7.4.2",
|
||||
"@ionic/core": "7.4.3",
|
||||
"ionicons": "^7.0.0",
|
||||
"tslib": "*"
|
||||
}
|
||||
@@ -3844,9 +3844,9 @@
|
||||
}
|
||||
},
|
||||
"@stencil/core": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.3.0.tgz",
|
||||
"integrity": "sha512-WYjftKg5fuqO7mf3nTl1aCRurkeMmfEF38WcBG4VLF6UPQ+MA76/koedGR2LGhATGByx+pbxR4iRxAr2Bspc9A=="
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.4.0.tgz",
|
||||
"integrity": "sha512-YlLyCqGBsMEuZb3XTO/STT0TX9eSwjoVhCJgtjVfQOF+ebIMVlojTh40CmDveWiWbth687cbr6S2heeussV8Sg=="
|
||||
},
|
||||
"@types/estree": {
|
||||
"version": "0.0.39",
|
||||
|
||||
28
packages/react/package-lock.json
generated
28
packages/react/package-lock.json
generated
@@ -697,19 +697,19 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@ionic/core": {
|
||||
"version": "7.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.4.2.tgz",
|
||||
"integrity": "sha512-ePuP+SxS6HY/nos267dBdAvL0kth1FYUWs8Y+DSM+FFTeRdEbvOsa2JeQCY7gCt/Ep9e7lSND95qfkX23pGNDA==",
|
||||
"version": "7.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.4.3.tgz",
|
||||
"integrity": "sha512-JPQLGojKnI/L0UBVshRv86DOSDj61rJRFYQImU4IcgP/rw5ckxwt3iZ5NtdJl0eEDwu91n68aGJdU+TFJjMJgQ==",
|
||||
"dependencies": {
|
||||
"@stencil/core": "^4.3.0",
|
||||
"@stencil/core": "^4.4.0",
|
||||
"ionicons": "7.1.0",
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@ionic/core/node_modules/@stencil/core": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.3.0.tgz",
|
||||
"integrity": "sha512-WYjftKg5fuqO7mf3nTl1aCRurkeMmfEF38WcBG4VLF6UPQ+MA76/koedGR2LGhATGByx+pbxR4iRxAr2Bspc9A==",
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.4.0.tgz",
|
||||
"integrity": "sha512-YlLyCqGBsMEuZb3XTO/STT0TX9eSwjoVhCJgtjVfQOF+ebIMVlojTh40CmDveWiWbth687cbr6S2heeussV8Sg==",
|
||||
"bin": {
|
||||
"stencil": "bin/stencil"
|
||||
},
|
||||
@@ -11778,19 +11778,19 @@
|
||||
"dev": true
|
||||
},
|
||||
"@ionic/core": {
|
||||
"version": "7.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.4.2.tgz",
|
||||
"integrity": "sha512-ePuP+SxS6HY/nos267dBdAvL0kth1FYUWs8Y+DSM+FFTeRdEbvOsa2JeQCY7gCt/Ep9e7lSND95qfkX23pGNDA==",
|
||||
"version": "7.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.4.3.tgz",
|
||||
"integrity": "sha512-JPQLGojKnI/L0UBVshRv86DOSDj61rJRFYQImU4IcgP/rw5ckxwt3iZ5NtdJl0eEDwu91n68aGJdU+TFJjMJgQ==",
|
||||
"requires": {
|
||||
"@stencil/core": "^4.3.0",
|
||||
"@stencil/core": "^4.4.0",
|
||||
"ionicons": "7.1.0",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@stencil/core": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.3.0.tgz",
|
||||
"integrity": "sha512-WYjftKg5fuqO7mf3nTl1aCRurkeMmfEF38WcBG4VLF6UPQ+MA76/koedGR2LGhATGByx+pbxR4iRxAr2Bspc9A=="
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.4.0.tgz",
|
||||
"integrity": "sha512-YlLyCqGBsMEuZb3XTO/STT0TX9eSwjoVhCJgtjVfQOF+ebIMVlojTh40CmDveWiWbth687cbr6S2heeussV8Sg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
44
packages/vue-router/package-lock.json
generated
44
packages/vue-router/package-lock.json
generated
@@ -660,11 +660,11 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@ionic/core": {
|
||||
"version": "7.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.4.2.tgz",
|
||||
"integrity": "sha512-ePuP+SxS6HY/nos267dBdAvL0kth1FYUWs8Y+DSM+FFTeRdEbvOsa2JeQCY7gCt/Ep9e7lSND95qfkX23pGNDA==",
|
||||
"version": "7.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.4.3.tgz",
|
||||
"integrity": "sha512-JPQLGojKnI/L0UBVshRv86DOSDj61rJRFYQImU4IcgP/rw5ckxwt3iZ5NtdJl0eEDwu91n68aGJdU+TFJjMJgQ==",
|
||||
"dependencies": {
|
||||
"@stencil/core": "^4.3.0",
|
||||
"@stencil/core": "^4.4.0",
|
||||
"ionicons": "7.1.0",
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
@@ -871,11 +871,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@ionic/vue": {
|
||||
"version": "7.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/vue/-/vue-7.4.2.tgz",
|
||||
"integrity": "sha512-zNYq40mJV2Gp0MBtllgEJXPxdvY9F3JYEhyfH6cn8xPOfhBz0pcSa5cMb8UcBql/Ut4LEEv0zaPLJ5KrP0hYiw==",
|
||||
"version": "7.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/vue/-/vue-7.4.3.tgz",
|
||||
"integrity": "sha512-DV/SExC/e3rcLoowuYb5bwo4N/oP5fWHQo1xLP654I/879hlwPJlCxdWFtaE2OlT3aEix9ssLYeNiWaxuK+9dQ==",
|
||||
"dependencies": {
|
||||
"@ionic/core": "7.4.2",
|
||||
"@ionic/core": "7.4.3",
|
||||
"ionicons": "^7.0.0"
|
||||
}
|
||||
},
|
||||
@@ -1323,9 +1323,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@stencil/core": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.3.0.tgz",
|
||||
"integrity": "sha512-WYjftKg5fuqO7mf3nTl1aCRurkeMmfEF38WcBG4VLF6UPQ+MA76/koedGR2LGhATGByx+pbxR4iRxAr2Bspc9A==",
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.4.0.tgz",
|
||||
"integrity": "sha512-YlLyCqGBsMEuZb3XTO/STT0TX9eSwjoVhCJgtjVfQOF+ebIMVlojTh40CmDveWiWbth687cbr6S2heeussV8Sg==",
|
||||
"bin": {
|
||||
"stencil": "bin/stencil"
|
||||
},
|
||||
@@ -7697,11 +7697,11 @@
|
||||
"dev": true
|
||||
},
|
||||
"@ionic/core": {
|
||||
"version": "7.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.4.2.tgz",
|
||||
"integrity": "sha512-ePuP+SxS6HY/nos267dBdAvL0kth1FYUWs8Y+DSM+FFTeRdEbvOsa2JeQCY7gCt/Ep9e7lSND95qfkX23pGNDA==",
|
||||
"version": "7.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.4.3.tgz",
|
||||
"integrity": "sha512-JPQLGojKnI/L0UBVshRv86DOSDj61rJRFYQImU4IcgP/rw5ckxwt3iZ5NtdJl0eEDwu91n68aGJdU+TFJjMJgQ==",
|
||||
"requires": {
|
||||
"@stencil/core": "^4.3.0",
|
||||
"@stencil/core": "^4.4.0",
|
||||
"ionicons": "7.1.0",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
@@ -7829,11 +7829,11 @@
|
||||
"requires": {}
|
||||
},
|
||||
"@ionic/vue": {
|
||||
"version": "7.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/vue/-/vue-7.4.2.tgz",
|
||||
"integrity": "sha512-zNYq40mJV2Gp0MBtllgEJXPxdvY9F3JYEhyfH6cn8xPOfhBz0pcSa5cMb8UcBql/Ut4LEEv0zaPLJ5KrP0hYiw==",
|
||||
"version": "7.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/vue/-/vue-7.4.3.tgz",
|
||||
"integrity": "sha512-DV/SExC/e3rcLoowuYb5bwo4N/oP5fWHQo1xLP654I/879hlwPJlCxdWFtaE2OlT3aEix9ssLYeNiWaxuK+9dQ==",
|
||||
"requires": {
|
||||
"@ionic/core": "7.4.2",
|
||||
"@ionic/core": "7.4.3",
|
||||
"ionicons": "^7.0.0"
|
||||
}
|
||||
},
|
||||
@@ -8192,9 +8192,9 @@
|
||||
}
|
||||
},
|
||||
"@stencil/core": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.3.0.tgz",
|
||||
"integrity": "sha512-WYjftKg5fuqO7mf3nTl1aCRurkeMmfEF38WcBG4VLF6UPQ+MA76/koedGR2LGhATGByx+pbxR4iRxAr2Bspc9A=="
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.4.0.tgz",
|
||||
"integrity": "sha512-YlLyCqGBsMEuZb3XTO/STT0TX9eSwjoVhCJgtjVfQOF+ebIMVlojTh40CmDveWiWbth687cbr6S2heeussV8Sg=="
|
||||
},
|
||||
"@tootallnate/once": {
|
||||
"version": "2.0.0",
|
||||
|
||||
28
packages/vue/package-lock.json
generated
28
packages/vue/package-lock.json
generated
@@ -207,11 +207,11 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@ionic/core": {
|
||||
"version": "7.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.4.2.tgz",
|
||||
"integrity": "sha512-ePuP+SxS6HY/nos267dBdAvL0kth1FYUWs8Y+DSM+FFTeRdEbvOsa2JeQCY7gCt/Ep9e7lSND95qfkX23pGNDA==",
|
||||
"version": "7.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.4.3.tgz",
|
||||
"integrity": "sha512-JPQLGojKnI/L0UBVshRv86DOSDj61rJRFYQImU4IcgP/rw5ckxwt3iZ5NtdJl0eEDwu91n68aGJdU+TFJjMJgQ==",
|
||||
"dependencies": {
|
||||
"@stencil/core": "^4.3.0",
|
||||
"@stencil/core": "^4.4.0",
|
||||
"ionicons": "7.1.0",
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
@@ -423,9 +423,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@stencil/core": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.3.0.tgz",
|
||||
"integrity": "sha512-WYjftKg5fuqO7mf3nTl1aCRurkeMmfEF38WcBG4VLF6UPQ+MA76/koedGR2LGhATGByx+pbxR4iRxAr2Bspc9A==",
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.4.0.tgz",
|
||||
"integrity": "sha512-YlLyCqGBsMEuZb3XTO/STT0TX9eSwjoVhCJgtjVfQOF+ebIMVlojTh40CmDveWiWbth687cbr6S2heeussV8Sg==",
|
||||
"bin": {
|
||||
"stencil": "bin/stencil"
|
||||
},
|
||||
@@ -3746,11 +3746,11 @@
|
||||
"dev": true
|
||||
},
|
||||
"@ionic/core": {
|
||||
"version": "7.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.4.2.tgz",
|
||||
"integrity": "sha512-ePuP+SxS6HY/nos267dBdAvL0kth1FYUWs8Y+DSM+FFTeRdEbvOsa2JeQCY7gCt/Ep9e7lSND95qfkX23pGNDA==",
|
||||
"version": "7.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.4.3.tgz",
|
||||
"integrity": "sha512-JPQLGojKnI/L0UBVshRv86DOSDj61rJRFYQImU4IcgP/rw5ckxwt3iZ5NtdJl0eEDwu91n68aGJdU+TFJjMJgQ==",
|
||||
"requires": {
|
||||
"@stencil/core": "^4.3.0",
|
||||
"@stencil/core": "^4.4.0",
|
||||
"ionicons": "7.1.0",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
@@ -3885,9 +3885,9 @@
|
||||
}
|
||||
},
|
||||
"@stencil/core": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.3.0.tgz",
|
||||
"integrity": "sha512-WYjftKg5fuqO7mf3nTl1aCRurkeMmfEF38WcBG4VLF6UPQ+MA76/koedGR2LGhATGByx+pbxR4iRxAr2Bspc9A=="
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.4.0.tgz",
|
||||
"integrity": "sha512-YlLyCqGBsMEuZb3XTO/STT0TX9eSwjoVhCJgtjVfQOF+ebIMVlojTh40CmDveWiWbth687cbr6S2heeussV8Sg=="
|
||||
},
|
||||
"@types/json-schema": {
|
||||
"version": "7.0.11",
|
||||
|
||||
Reference in New Issue
Block a user