mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-16 01:52:19 +08:00
feat(vue): add custom elements bundle (#23458)
This commit is contained in:
@ -1,10 +1,11 @@
|
||||
import { defineComponent, h, ref, VNode } from 'vue';
|
||||
import { defineCustomElement } from '../utils';
|
||||
|
||||
export interface OverlayProps {
|
||||
isOpen?: boolean;
|
||||
}
|
||||
|
||||
export const defineOverlayContainer = <Props extends object>(name: string, componentProps: string[] = [], controller: any) => {
|
||||
export const defineOverlayContainer = <Props extends object>(name: string, customElement: any, componentProps: string[] = [], controller: any) => {
|
||||
const eventListeners = [
|
||||
{ componentEv: `${name}-will-present`, frameworkEv: 'willPresent' },
|
||||
{ componentEv: `${name}-did-present`, frameworkEv: 'didPresent' },
|
||||
@ -13,6 +14,8 @@ export const defineOverlayContainer = <Props extends object>(name: string, compo
|
||||
];
|
||||
|
||||
const Container = defineComponent<Props & OverlayProps>((props, { slots, emit }) => {
|
||||
defineCustomElement(name, customElement);
|
||||
|
||||
const overlay = ref();
|
||||
const onVnodeMounted = async () => {
|
||||
const isOpen = props.isOpen;
|
||||
|
@ -14,12 +14,6 @@ interface NavManager<T = any> {
|
||||
navigate: (options: T) => void;
|
||||
}
|
||||
|
||||
interface ComponentOptions {
|
||||
modelProp?: string;
|
||||
modelUpdateEvent?: string | string[];
|
||||
externalModelUpdateEvent?: string;
|
||||
}
|
||||
|
||||
const getComponentClasses = (classes: unknown) => {
|
||||
return (classes as string)?.split(' ') || [];
|
||||
};
|
||||
@ -36,18 +30,35 @@ const getElementClasses = (ref: Ref<HTMLElement | undefined>, componentClasses:
|
||||
* @prop componentProps - An array of properties on the
|
||||
* component. These usually match up with the @Prop definitions
|
||||
* in each component's TSX file.
|
||||
* @prop componentOptions - An object that defines additional
|
||||
* options for the component such as router or v-model
|
||||
* integrations.
|
||||
* @prop customElement - An option custom element instance to pass
|
||||
* to customElements.define. Only set if `includeImportCustomElements: true` in your config.
|
||||
* @prop modelProp - The prop that v-model binds to (i.e. value)
|
||||
* @prop modelUpdateEvent - The event that is fired from your Web Component when the value changes (i.e. ionChange)
|
||||
* @prop externalModelUpdateEvent - The external event to fire from your Vue component when modelUpdateEvent fires. This is used for ensuring that v-model references have been
|
||||
* correctly updated when a user's event callback fires.
|
||||
*/
|
||||
export const defineContainer = <Props>(name: string, componentProps: string[] = [], componentOptions: ComponentOptions = {}) => {
|
||||
const { modelProp, modelUpdateEvent, externalModelUpdateEvent } = componentOptions;
|
||||
|
||||
export const defineContainer = <Props>(
|
||||
name: string,
|
||||
customElement: any,
|
||||
componentProps: string[] = [],
|
||||
modelProp?: string,
|
||||
modelUpdateEvent?: string,
|
||||
externalModelUpdateEvent?: string
|
||||
) => {
|
||||
/**
|
||||
* Create a Vue component wrapper around a Web Component.
|
||||
* Note: The `props` here are not all properties on a component.
|
||||
* They refer to whatever properties are set on an instance of a component.
|
||||
*/
|
||||
|
||||
if (
|
||||
customElement !== undefined &&
|
||||
typeof customElements !== 'undefined' &&
|
||||
!customElements.get(name)
|
||||
) {
|
||||
customElements.define(name, customElement);
|
||||
}
|
||||
|
||||
const Container = defineComponent<Props & InputProps>((props, { attrs, slots, emit }) => {
|
||||
let modelPropValue = (props as any)[modelProp];
|
||||
const containerRef = ref<HTMLElement>();
|
||||
@ -69,7 +80,9 @@ export const defineContainer = <Props>(name: string, componentProps: string[] =
|
||||
* native web component, but the v-model will
|
||||
* not have been updated yet.
|
||||
*/
|
||||
emit(externalModelUpdateEvent, e);
|
||||
if (externalModelUpdateEvent) {
|
||||
emit(externalModelUpdateEvent, e);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -117,13 +130,21 @@ export const defineContainer = <Props>(name: string, componentProps: string[] =
|
||||
ref: containerRef,
|
||||
class: getElementClasses(containerRef, classes),
|
||||
onClick: handleClick,
|
||||
onVnodeBeforeMount: (modelUpdateEvent && externalModelUpdateEvent) ? onVnodeBeforeMount : undefined
|
||||
onVnodeBeforeMount: (modelUpdateEvent) ? onVnodeBeforeMount : undefined
|
||||
};
|
||||
|
||||
if (modelProp) {
|
||||
/**
|
||||
* Starting in Vue 3.1.0, all properties are
|
||||
* added as keys to the props object, even if
|
||||
* they are not being used. In order to correctly
|
||||
* account for both value props and v-model props,
|
||||
* we need to check if the key exists for Vue <3.1.0
|
||||
* and then check if it is not undefined for Vue >= 3.1.0.
|
||||
*/
|
||||
propsToAdd = {
|
||||
...propsToAdd,
|
||||
[modelProp]: props.hasOwnProperty('modelValue') ? props.modelValue : modelPropValue
|
||||
[modelProp]: props.hasOwnProperty(MODEL_VALUE) && props[MODEL_VALUE] !== undefined ? props.modelValue : modelPropValue
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user