mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-16 10:01:59 +08:00
fix(vue): update output target and properly emit events (#30227)
Issue number: resolves #30206 resolves #30178 resolves #30177 resolves #30175 resolves #30170 --------- <!-- Please do not submit updates to dependencies unless it fixes an issue. --> <!-- Please try to limit your pull request to one type (bugfix, feature, etc). Submit multiple pull requests if needed. --> ## What is the current behavior? There have been plenty of issues reported in regards to Vue components failing to propagate events. It seems like when we updated the Vue output target and started to use the provided runtime code from the output target, we have changed the way how event names are computed. Ionic has used a custom wrapper for handling events that would kebab case event names. That is no longer needed and removing it fixes observed issues. Reproduction case working: https://stackblitz.com/edit/vj18czas-wdhzxjom?file=package.json ## What is the new behavior? We have received a fix for this in https://github.com/stenciljs/output-targets/pull/617 which I hope will resolve this issue by updating the dependency. ## Does this introduce a breaking change? - [ ] Yes - [x] No <!-- If this introduces a breaking change: 1. Describe the impact and migration path for existing applications below. 2. Update the BREAKING.md file with the breaking change. 3. Add "BREAKING CHANGE: [...]" to the commit description when merging. See https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer for more information. --> ## Other information Dev build: `8.4.4-dev.11741193800.14916f6f`
This commit is contained in:

committed by
GitHub

parent
ba8d8f4896
commit
11554a5d35
15
core/package-lock.json
generated
15
core/package-lock.json
generated
@ -28,7 +28,7 @@
|
|||||||
"@stencil/angular-output-target": "^0.10.0",
|
"@stencil/angular-output-target": "^0.10.0",
|
||||||
"@stencil/react-output-target": "0.5.3",
|
"@stencil/react-output-target": "0.5.3",
|
||||||
"@stencil/sass": "^3.0.9",
|
"@stencil/sass": "^3.0.9",
|
||||||
"@stencil/vue-output-target": "^0.9.0",
|
"@stencil/vue-output-target": "^0.9.6",
|
||||||
"@types/jest": "^29.5.6",
|
"@types/jest": "^29.5.6",
|
||||||
"@types/node": "^14.6.0",
|
"@types/node": "^14.6.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^6.7.2",
|
"@typescript-eslint/eslint-plugin": "^6.7.2",
|
||||||
@ -1850,10 +1850,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@stencil/vue-output-target": {
|
"node_modules/@stencil/vue-output-target": {
|
||||||
"version": "0.9.2",
|
"version": "0.9.6",
|
||||||
"resolved": "https://registry.npmjs.org/@stencil/vue-output-target/-/vue-output-target-0.9.2.tgz",
|
"resolved": "https://registry.npmjs.org/@stencil/vue-output-target/-/vue-output-target-0.9.6.tgz",
|
||||||
"integrity": "sha512-AeBmfo8bQhtob4VKpYTNiCoqh50MeXUwRgYLyO/JxRgAAK9GSfenNrUxXDrK0DK65SWsx/GCOsRwWbfOveorOQ==",
|
"integrity": "sha512-IxLknP+bZ2Di3EOEtd8ozh/9JHyoFyvfO+gapO7IpSjT1zFoEfIpFN0/IZPKN6VNI5lMrQ3BFIRs9C689g7VsQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@stencil/core": ">=2.0.0 || >=3 || >= 4.0.0-beta.0 || >= 4.0.0",
|
"@stencil/core": ">=2.0.0 || >=3 || >= 4.0.0-beta.0 || >= 4.0.0",
|
||||||
"vue": "^3.4.38"
|
"vue": "^3.4.38"
|
||||||
@ -11834,9 +11835,9 @@
|
|||||||
"requires": {}
|
"requires": {}
|
||||||
},
|
},
|
||||||
"@stencil/vue-output-target": {
|
"@stencil/vue-output-target": {
|
||||||
"version": "0.9.2",
|
"version": "0.9.6",
|
||||||
"resolved": "https://registry.npmjs.org/@stencil/vue-output-target/-/vue-output-target-0.9.2.tgz",
|
"resolved": "https://registry.npmjs.org/@stencil/vue-output-target/-/vue-output-target-0.9.6.tgz",
|
||||||
"integrity": "sha512-AeBmfo8bQhtob4VKpYTNiCoqh50MeXUwRgYLyO/JxRgAAK9GSfenNrUxXDrK0DK65SWsx/GCOsRwWbfOveorOQ==",
|
"integrity": "sha512-IxLknP+bZ2Di3EOEtd8ozh/9JHyoFyvfO+gapO7IpSjT1zFoEfIpFN0/IZPKN6VNI5lMrQ3BFIRs9C689g7VsQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {}
|
"requires": {}
|
||||||
},
|
},
|
||||||
|
@ -50,7 +50,7 @@
|
|||||||
"@stencil/angular-output-target": "^0.10.0",
|
"@stencil/angular-output-target": "^0.10.0",
|
||||||
"@stencil/react-output-target": "0.5.3",
|
"@stencil/react-output-target": "0.5.3",
|
||||||
"@stencil/sass": "^3.0.9",
|
"@stencil/sass": "^3.0.9",
|
||||||
"@stencil/vue-output-target": "^0.9.0",
|
"@stencil/vue-output-target": "^0.9.6",
|
||||||
"@types/jest": "^29.5.6",
|
"@types/jest": "^29.5.6",
|
||||||
"@types/node": "^14.6.0",
|
"@types/node": "^14.6.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^6.7.2",
|
"@typescript-eslint/eslint-plugin": "^6.7.2",
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { getMode, setMode, setPlatformHelpers } from '@stencil/core';
|
import { getMode, setMode } from '@stencil/core';
|
||||||
|
|
||||||
import type { IonicConfig, Mode } from '../interface';
|
import type { IonicConfig, Mode } from '../interface';
|
||||||
import { isPlatform, setupPlatforms } from '../utils/platform';
|
import { isPlatform, setupPlatforms } from '../utils/platform';
|
||||||
@ -22,18 +22,6 @@ export const initialize = (userConfig: IonicConfig = {}) => {
|
|||||||
const win = window;
|
const win = window;
|
||||||
const Ionic = ((win as any).Ionic = (win as any).Ionic || {});
|
const Ionic = ((win as any).Ionic = (win as any).Ionic || {});
|
||||||
|
|
||||||
const platformHelpers: any = {};
|
|
||||||
if (userConfig._ael) {
|
|
||||||
platformHelpers.ael = userConfig._ael;
|
|
||||||
}
|
|
||||||
if (userConfig._rel) {
|
|
||||||
platformHelpers.rel = userConfig._rel;
|
|
||||||
}
|
|
||||||
if (userConfig._ce) {
|
|
||||||
platformHelpers.ce = userConfig._ce;
|
|
||||||
}
|
|
||||||
setPlatformHelpers(platformHelpers);
|
|
||||||
|
|
||||||
// create the Ionic.config from raw config object (if it exists)
|
// create the Ionic.config from raw config object (if it exists)
|
||||||
// and convert Ionic.config into a ConfigApi that has a get() fn
|
// and convert Ionic.config into a ConfigApi that has a get() fn
|
||||||
const configObj = {
|
const configObj = {
|
||||||
|
@ -234,9 +234,6 @@ export interface IonicConfig {
|
|||||||
_forceStatusbarPadding?: boolean;
|
_forceStatusbarPadding?: boolean;
|
||||||
_testing?: boolean;
|
_testing?: boolean;
|
||||||
_zoneGate?: (h: () => any) => any;
|
_zoneGate?: (h: () => any) => any;
|
||||||
_ael?: (el: any, name: string, cb: any, opts: any) => any;
|
|
||||||
_rel?: (el: any, name: string, cb: any, opts: any) => any;
|
|
||||||
_ce?: (eventName: string, opts: any) => any;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type FocusManagerPriority = 'content' | 'heading' | 'banner';
|
type FocusManagerPriority = 'content' | 'heading' | 'banner';
|
||||||
|
@ -42,7 +42,7 @@ const transitionEnd = (el: HTMLElement | null, expectedDuration = 0, callback: (
|
|||||||
if (el) {
|
if (el) {
|
||||||
el.addEventListener('webkitTransitionEnd', onTransitionEnd, opts);
|
el.addEventListener('webkitTransitionEnd', onTransitionEnd, opts);
|
||||||
el.addEventListener('transitionend', onTransitionEnd, opts);
|
el.addEventListener('transitionend', onTransitionEnd, opts);
|
||||||
animationTimeout = setTimeout(onTransitionEnd, expectedDuration + ANIMATION_FALLBACK_TIMEOUT);
|
animationTimeout = setTimeout(onTransitionEnd, expectedDuration + ANIMATION_FALLBACK_TIMEOUT) as unknown as number;
|
||||||
|
|
||||||
unRegTrans = () => {
|
unRegTrans = () => {
|
||||||
if (animationTimeout !== undefined) {
|
if (animationTimeout !== undefined) {
|
||||||
@ -190,36 +190,10 @@ export const inheritAriaAttributes = (el: HTMLElement, ignoreList?: string[]) =>
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const addEventListener = (el: any, eventName: string, callback: any, opts?: any) => {
|
export const addEventListener = (el: any, eventName: string, callback: any, opts?: any) => {
|
||||||
if (typeof (window as any) !== 'undefined') {
|
|
||||||
const win = window as any;
|
|
||||||
const config = win?.Ionic?.config;
|
|
||||||
if (config) {
|
|
||||||
const ael = config.get('_ael');
|
|
||||||
if (ael) {
|
|
||||||
return ael(el, eventName, callback, opts);
|
|
||||||
} else if (config._ael) {
|
|
||||||
return config._ael(el, eventName, callback, opts);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return el.addEventListener(eventName, callback, opts);
|
return el.addEventListener(eventName, callback, opts);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const removeEventListener = (el: any, eventName: string, callback: any, opts?: any) => {
|
export const removeEventListener = (el: any, eventName: string, callback: any, opts?: any) => {
|
||||||
if (typeof (window as any) !== 'undefined') {
|
|
||||||
const win = window as any;
|
|
||||||
const config = win?.Ionic?.config;
|
|
||||||
if (config) {
|
|
||||||
const rel = config.get('_rel');
|
|
||||||
if (rel) {
|
|
||||||
return rel(el, eventName, callback, opts);
|
|
||||||
} else if (config._rel) {
|
|
||||||
return config._rel(el, eventName, callback, opts);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return el.removeEventListener(eventName, callback, opts);
|
return el.removeEventListener(eventName, callback, opts);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
14
packages/vue/package-lock.json
generated
14
packages/vue/package-lock.json
generated
@ -18,7 +18,7 @@
|
|||||||
"@ionic/prettier-config": "^2.0.0",
|
"@ionic/prettier-config": "^2.0.0",
|
||||||
"@rollup/plugin-node-resolve": "^16.0.0",
|
"@rollup/plugin-node-resolve": "^16.0.0",
|
||||||
"@rollup/plugin-typescript": "^11.1.5",
|
"@rollup/plugin-typescript": "^11.1.5",
|
||||||
"@stencil/vue-output-target": "0.9.4",
|
"@stencil/vue-output-target": "0.9.6",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.48.2",
|
"@typescript-eslint/eslint-plugin": "^5.48.2",
|
||||||
"@typescript-eslint/parser": "^5.48.2",
|
"@typescript-eslint/parser": "^5.48.2",
|
||||||
"change-case": "^4.1.1",
|
"change-case": "^4.1.1",
|
||||||
@ -691,9 +691,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@stencil/vue-output-target": {
|
"node_modules/@stencil/vue-output-target": {
|
||||||
"version": "0.9.4",
|
"version": "0.9.6",
|
||||||
"resolved": "https://registry.npmjs.org/@stencil/vue-output-target/-/vue-output-target-0.9.4.tgz",
|
"resolved": "https://registry.npmjs.org/@stencil/vue-output-target/-/vue-output-target-0.9.6.tgz",
|
||||||
"integrity": "sha512-nXt1ZKjQ8n+ZaKbj1gcutqcgt7SCwVYzNxa1LfKpKz4L1DST33k1/goahvFeWO/lJzLm47spPtHfcjeaLUg/iQ==",
|
"integrity": "sha512-IxLknP+bZ2Di3EOEtd8ozh/9JHyoFyvfO+gapO7IpSjT1zFoEfIpFN0/IZPKN6VNI5lMrQ3BFIRs9C689g7VsQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
@ -4342,9 +4342,9 @@
|
|||||||
"integrity": "sha512-WPrTHFngvN081RY+dJPneKQLwnOFD60OMCOQGmmSHfCW0f4ujPMzzhwWU1gcSwXPWXz5O+8cBiiCaxAbJU7kAg=="
|
"integrity": "sha512-WPrTHFngvN081RY+dJPneKQLwnOFD60OMCOQGmmSHfCW0f4ujPMzzhwWU1gcSwXPWXz5O+8cBiiCaxAbJU7kAg=="
|
||||||
},
|
},
|
||||||
"@stencil/vue-output-target": {
|
"@stencil/vue-output-target": {
|
||||||
"version": "0.9.4",
|
"version": "0.9.6",
|
||||||
"resolved": "https://registry.npmjs.org/@stencil/vue-output-target/-/vue-output-target-0.9.4.tgz",
|
"resolved": "https://registry.npmjs.org/@stencil/vue-output-target/-/vue-output-target-0.9.6.tgz",
|
||||||
"integrity": "sha512-nXt1ZKjQ8n+ZaKbj1gcutqcgt7SCwVYzNxa1LfKpKz4L1DST33k1/goahvFeWO/lJzLm47spPtHfcjeaLUg/iQ==",
|
"integrity": "sha512-IxLknP+bZ2Di3EOEtd8ozh/9JHyoFyvfO+gapO7IpSjT1zFoEfIpFN0/IZPKN6VNI5lMrQ3BFIRs9C689g7VsQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {}
|
"requires": {}
|
||||||
},
|
},
|
||||||
|
@ -54,7 +54,7 @@
|
|||||||
"@ionic/prettier-config": "^2.0.0",
|
"@ionic/prettier-config": "^2.0.0",
|
||||||
"@rollup/plugin-node-resolve": "^16.0.0",
|
"@rollup/plugin-node-resolve": "^16.0.0",
|
||||||
"@rollup/plugin-typescript": "^11.1.5",
|
"@rollup/plugin-typescript": "^11.1.5",
|
||||||
"@stencil/vue-output-target": "0.9.4",
|
"@stencil/vue-output-target": "0.9.6",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.48.2",
|
"@typescript-eslint/eslint-plugin": "^5.48.2",
|
||||||
"@typescript-eslint/parser": "^5.48.2",
|
"@typescript-eslint/parser": "^5.48.2",
|
||||||
"change-case": "^4.1.1",
|
"change-case": "^4.1.1",
|
||||||
|
@ -2,25 +2,6 @@ import type { IonicConfig } from "@ionic/core/components";
|
|||||||
import { initialize } from "@ionic/core/components";
|
import { initialize } from "@ionic/core/components";
|
||||||
import type { App, Plugin } from "vue";
|
import type { App, Plugin } from "vue";
|
||||||
|
|
||||||
// TODO(FW-2969): types
|
|
||||||
|
|
||||||
const toKebabCase = (eventName: string) => {
|
|
||||||
return eventName
|
|
||||||
.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g, "$1-$2")
|
|
||||||
.toLowerCase();
|
|
||||||
};
|
|
||||||
|
|
||||||
const getHelperFunctions = () => {
|
|
||||||
return {
|
|
||||||
ael: (el: any, eventName: string, cb: any, opts: any) =>
|
|
||||||
el.addEventListener(toKebabCase(eventName), cb, opts),
|
|
||||||
rel: (el: any, eventName: string, cb: any, opts: any) =>
|
|
||||||
el.removeEventListener(toKebabCase(eventName), cb, opts),
|
|
||||||
ce: (eventName: string, opts: any) =>
|
|
||||||
new CustomEvent(toKebabCase(eventName), opts),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export const IonicVue: Plugin<[IonicConfig?]> = {
|
export const IonicVue: Plugin<[IonicConfig?]> = {
|
||||||
async install(_: App, config: IonicConfig = {}) {
|
async install(_: App, config: IonicConfig = {}) {
|
||||||
/**
|
/**
|
||||||
@ -34,12 +15,6 @@ export const IonicVue: Plugin<[IonicConfig?]> = {
|
|||||||
document.documentElement.classList.add("ion-ce");
|
document.documentElement.classList.add("ion-ce");
|
||||||
}
|
}
|
||||||
|
|
||||||
const { ael, rel, ce } = getHelperFunctions();
|
initialize(config);
|
||||||
initialize({
|
|
||||||
...config,
|
|
||||||
_ael: ael,
|
|
||||||
_rel: rel,
|
|
||||||
_ce: ce,
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -20,10 +20,10 @@ export const defineOverlayContainer = <Props extends object>(
|
|||||||
const createControllerComponent = (options: ComponentOptions) => {
|
const createControllerComponent = (options: ComponentOptions) => {
|
||||||
return defineComponent<Props & OverlayProps>((props, { slots, emit }) => {
|
return defineComponent<Props & OverlayProps>((props, { slots, emit }) => {
|
||||||
const eventListeners = [
|
const eventListeners = [
|
||||||
{ componentEv: `${name}-will-present`, frameworkEv: "willPresent" },
|
{ componentEv: `${name}WillPresent`, frameworkEv: "willPresent" },
|
||||||
{ componentEv: `${name}-did-present`, frameworkEv: "didPresent" },
|
{ componentEv: `${name}DidPresent`, frameworkEv: "didPresent" },
|
||||||
{ componentEv: `${name}-will-dismiss`, frameworkEv: "willDismiss" },
|
{ componentEv: `${name}WillDismiss`, frameworkEv: "willDismiss" },
|
||||||
{ componentEv: `${name}-did-dismiss`, frameworkEv: "didDismiss" },
|
{ componentEv: `${name}DidDismiss`, frameworkEv: "didDismiss" },
|
||||||
];
|
];
|
||||||
|
|
||||||
if (defineCustomElement !== undefined) {
|
if (defineCustomElement !== undefined) {
|
||||||
@ -139,7 +139,7 @@ export const defineOverlayContainer = <Props extends object>(
|
|||||||
}, options);
|
}, options);
|
||||||
};
|
};
|
||||||
const createInlineComponent = (options: any) => {
|
const createInlineComponent = (options: any) => {
|
||||||
return defineComponent((props, { slots }) => {
|
return defineComponent((props, { slots, emit }) => {
|
||||||
if (defineCustomElement !== undefined) {
|
if (defineCustomElement !== undefined) {
|
||||||
defineCustomElement();
|
defineCustomElement();
|
||||||
}
|
}
|
||||||
@ -147,18 +147,24 @@ export const defineOverlayContainer = <Props extends object>(
|
|||||||
const elementRef = ref();
|
const elementRef = ref();
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
elementRef.value.addEventListener(
|
elementRef.value.addEventListener("ionMount", (ev: Event) => {
|
||||||
"ion-mount",
|
emit("ionMount", ev);
|
||||||
() => (isOpen.value = true)
|
isOpen.value = true;
|
||||||
);
|
});
|
||||||
elementRef.value.addEventListener(
|
elementRef.value.addEventListener("willPresent", (ev: Event) => {
|
||||||
"will-present",
|
emit("willPresent", ev);
|
||||||
() => (isOpen.value = true)
|
isOpen.value = true;
|
||||||
);
|
});
|
||||||
elementRef.value.addEventListener(
|
elementRef.value.addEventListener("didDismiss", (ev: Event) => {
|
||||||
"did-dismiss",
|
emit("didDismiss", ev);
|
||||||
() => (isOpen.value = false)
|
isOpen.value = false;
|
||||||
);
|
});
|
||||||
|
elementRef.value.addEventListener("willDismiss", (ev: Event) => {
|
||||||
|
emit("willDismiss", ev);
|
||||||
|
});
|
||||||
|
elementRef.value.addEventListener("didPresent", (ev: Event) => {
|
||||||
|
emit("didPresent", ev);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
|
Reference in New Issue
Block a user