mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
chore(angular): generate standalone component wrappers (#27970)
Issue number: N/A --------- <!-- 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? <!-- Please describe the current behavior that you are modifying. --> Ionic Framework currently only generates the lazy/hydrated Angular component wrappers for the web components. ## What is the new behavior? <!-- Please describe the behavior or changes that are being added by this PR. --> - Generates Angular standalone component wrappers for the web components, using the CE build. - Adds manual component wrapper for `ion-icon` with the CE build. - Migrates the `ion-back-button` and `ion-nav` to be manual component wrappers - Continues to generate the lazy/hydrated Angular component wrappers. - Refactors "NavDelegate" etc. language to `IonNav` to avoid exporting as and simplify navigating the code. ## Does this introduce a breaking change? - [ ] Yes - [x] No <!-- If this introduces a breaking change, please describe the impact and migration path for existing applications below. --> ## Other information <!-- Any other information that is important to this PR such as screenshots of how the component looks before and after the change. --> Related output targets PR: https://github.com/ionic-team/stencil-ds-output-targets/pull/367
This commit is contained in:
14
core/package-lock.json
generated
14
core/package-lock.json
generated
@@ -25,7 +25,7 @@
|
||||
"@playwright/test": "^1.36.1",
|
||||
"@rollup/plugin-node-resolve": "^8.4.0",
|
||||
"@rollup/plugin-virtual": "^2.0.3",
|
||||
"@stencil/angular-output-target": "^0.7.1",
|
||||
"@stencil/angular-output-target": "^0.8.1",
|
||||
"@stencil/react-output-target": "^0.5.3",
|
||||
"@stencil/sass": "^3.0.4",
|
||||
"@stencil/vue-output-target": "^0.8.6",
|
||||
@@ -1625,9 +1625,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@stencil/angular-output-target": {
|
||||
"version": "0.7.1",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/angular-output-target/-/angular-output-target-0.7.1.tgz",
|
||||
"integrity": "sha512-lxJbCAbyAQVAKGgEpNTjSF7GZZszbrJnNdNVgzuD1hLRFJyElA6kUSL0GQrZMbiPG5lC/cYdbQwpyWHX4xN8mw==",
|
||||
"version": "0.8.1",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/angular-output-target/-/angular-output-target-0.8.1.tgz",
|
||||
"integrity": "sha512-nO04lC7JxUT0bi2sTvBslz6aut1dVOvYRckf29a0l08XnRsDzIfT5e6f+c5HL9vCl4UFRq8fTQ+Og/G7Hlwtng==",
|
||||
"dev": true,
|
||||
"peerDependencies": {
|
||||
"@stencil/core": ">=2.0.0 || >=3 || >= 4.0.0-beta.0 || >= 4.0.0"
|
||||
@@ -11513,9 +11513,9 @@
|
||||
}
|
||||
},
|
||||
"@stencil/angular-output-target": {
|
||||
"version": "0.7.1",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/angular-output-target/-/angular-output-target-0.7.1.tgz",
|
||||
"integrity": "sha512-lxJbCAbyAQVAKGgEpNTjSF7GZZszbrJnNdNVgzuD1hLRFJyElA6kUSL0GQrZMbiPG5lC/cYdbQwpyWHX4xN8mw==",
|
||||
"version": "0.8.1",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/angular-output-target/-/angular-output-target-0.8.1.tgz",
|
||||
"integrity": "sha512-nO04lC7JxUT0bi2sTvBslz6aut1dVOvYRckf29a0l08XnRsDzIfT5e6f+c5HL9vCl4UFRq8fTQ+Og/G7Hlwtng==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
"@playwright/test": "^1.36.1",
|
||||
"@rollup/plugin-node-resolve": "^8.4.0",
|
||||
"@rollup/plugin-virtual": "^2.0.3",
|
||||
"@stencil/angular-output-target": "^0.7.1",
|
||||
"@stencil/angular-output-target": "^0.8.1",
|
||||
"@stencil/react-output-target": "^0.5.3",
|
||||
"@stencil/sass": "^3.0.4",
|
||||
"@stencil/vue-output-target": "^0.8.6",
|
||||
|
||||
@@ -7,6 +7,56 @@ import { vueOutputTarget } from '@stencil/vue-output-target';
|
||||
// @ts-ignore
|
||||
import { apiSpecGenerator } from './scripts/api-spec-generator';
|
||||
|
||||
const componentCorePackage = '@ionic/core';
|
||||
|
||||
const getAngularOutputTargets = () => {
|
||||
const excludeComponents = [
|
||||
// overlays that accept user components
|
||||
'ion-modal',
|
||||
'ion-popover',
|
||||
|
||||
// navigation
|
||||
'ion-router',
|
||||
'ion-route',
|
||||
'ion-route-redirect',
|
||||
'ion-router-link',
|
||||
'ion-router-outlet',
|
||||
'ion-nav',
|
||||
'ion-back-button',
|
||||
|
||||
// tabs
|
||||
'ion-tabs',
|
||||
'ion-tab',
|
||||
|
||||
// auxiliar
|
||||
'ion-picker-column',
|
||||
]
|
||||
return [
|
||||
angularOutputTarget({
|
||||
componentCorePackage,
|
||||
directivesProxyFile: '../packages/angular/src/directives/proxies.ts',
|
||||
directivesArrayFile: '../packages/angular/src/directives/proxies-list.ts',
|
||||
excludeComponents,
|
||||
outputType: 'component',
|
||||
}),
|
||||
angularOutputTarget({
|
||||
componentCorePackage,
|
||||
directivesProxyFile: '../packages/angular/standalone/src/directives/proxies.ts',
|
||||
excludeComponents: [
|
||||
...excludeComponents,
|
||||
/**
|
||||
* IonIcon is a special case because it does not come
|
||||
* from the `@ionic/core` package, so generating proxies that
|
||||
* are reliant on the CE build will reference the wrong
|
||||
* import location.
|
||||
*/
|
||||
'ion-icon'
|
||||
],
|
||||
outputType: 'standalone',
|
||||
})
|
||||
];
|
||||
}
|
||||
|
||||
export const config: Config = {
|
||||
autoprefixCss: true,
|
||||
sourceMap: false,
|
||||
@@ -61,7 +111,7 @@ export const config: Config = {
|
||||
],
|
||||
outputTargets: [
|
||||
reactOutputTarget({
|
||||
componentCorePackage: '@ionic/core',
|
||||
componentCorePackage,
|
||||
includeImportCustomElements: true,
|
||||
includePolyfills: false,
|
||||
includeDefineCustomElements: false,
|
||||
@@ -98,7 +148,7 @@ export const config: Config = {
|
||||
]
|
||||
}),
|
||||
vueOutputTarget({
|
||||
componentCorePackage: '@ionic/core',
|
||||
componentCorePackage,
|
||||
includeImportCustomElements: true,
|
||||
includePolyfills: false,
|
||||
includeDefineCustomElements: false,
|
||||
@@ -182,30 +232,7 @@ export const config: Config = {
|
||||
// type: 'stats',
|
||||
// file: 'stats.json'
|
||||
// },
|
||||
angularOutputTarget({
|
||||
componentCorePackage: '@ionic/core',
|
||||
directivesProxyFile: '../packages/angular/src/directives/proxies.ts',
|
||||
directivesArrayFile: '../packages/angular/src/directives/proxies-list.ts',
|
||||
excludeComponents: [
|
||||
// overlays that accept user components
|
||||
'ion-modal',
|
||||
'ion-popover',
|
||||
|
||||
// navigation
|
||||
'ion-router',
|
||||
'ion-route',
|
||||
'ion-route-redirect',
|
||||
'ion-router-link',
|
||||
'ion-router-outlet',
|
||||
|
||||
// tabs
|
||||
'ion-tabs',
|
||||
'ion-tab',
|
||||
|
||||
// auxiliar
|
||||
'ion-picker-column',
|
||||
],
|
||||
}),
|
||||
...getAngularOutputTargets(),
|
||||
],
|
||||
buildEs5: 'prod',
|
||||
testing: {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Directive, HostListener, Input, Optional, ElementRef, NgZone } from '@angular/core';
|
||||
import { HostListener, Input, Optional, ElementRef, NgZone, ChangeDetectorRef, Directive } from '@angular/core';
|
||||
import type { Components } from '@ionic/core';
|
||||
import type { AnimationBuilder } from '@ionic/core/components';
|
||||
|
||||
import { Config } from '../../providers/config';
|
||||
@@ -9,21 +10,23 @@ import { IonRouterOutlet } from './router-outlet';
|
||||
|
||||
const BACK_BUTTON_INPUTS = ['color', 'defaultHref', 'disabled', 'icon', 'mode', 'routerAnimation', 'text', 'type'];
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||
export declare interface IonBackButton extends Components.IonBackButton {}
|
||||
|
||||
@ProxyCmp({
|
||||
inputs: BACK_BUTTON_INPUTS,
|
||||
})
|
||||
@Directive({
|
||||
selector: 'ion-back-button',
|
||||
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
|
||||
inputs: BACK_BUTTON_INPUTS,
|
||||
})
|
||||
// eslint-disable-next-line @angular-eslint/directive-class-suffix
|
||||
export class IonBackButtonDelegate {
|
||||
export class IonBackButton {
|
||||
@Input()
|
||||
defaultHref: string | undefined | null;
|
||||
defaultHref: string | undefined;
|
||||
|
||||
@Input()
|
||||
routerAnimation?: AnimationBuilder;
|
||||
routerAnimation: AnimationBuilder | undefined;
|
||||
|
||||
protected el: HTMLElement;
|
||||
|
||||
@@ -32,8 +35,10 @@ export class IonBackButtonDelegate {
|
||||
private navCtrl: NavController,
|
||||
private config: Config,
|
||||
private r: ElementRef,
|
||||
protected z: NgZone
|
||||
protected z: NgZone,
|
||||
c: ChangeDetectorRef
|
||||
) {
|
||||
c.detach();
|
||||
this.el = this.r.nativeElement;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { ElementRef, Injector, Directive, EnvironmentInjector, NgZone } from '@angular/core';
|
||||
import { ElementRef, Injector, EnvironmentInjector, NgZone, ChangeDetectorRef, Directive } from '@angular/core';
|
||||
import type { Components } from '@ionic/core';
|
||||
|
||||
import { AngularDelegate } from '../../providers/angular-delegate';
|
||||
import { ProxyCmp, proxyOutputs } from '../../utils/proxy';
|
||||
@@ -21,25 +22,29 @@ const NAV_METHODS = [
|
||||
'getPrevious',
|
||||
];
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||
export declare interface IonNav extends Components.IonNav {}
|
||||
|
||||
@ProxyCmp({
|
||||
inputs: NAV_INPUTS,
|
||||
methods: NAV_METHODS,
|
||||
})
|
||||
@Directive({
|
||||
selector: 'ion-nav',
|
||||
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
|
||||
inputs: NAV_INPUTS,
|
||||
})
|
||||
// eslint-disable-next-line @angular-eslint/directive-class-suffix
|
||||
export class NavDelegate {
|
||||
export class IonNav {
|
||||
protected el: HTMLElement;
|
||||
constructor(
|
||||
ref: ElementRef,
|
||||
environmentInjector: EnvironmentInjector,
|
||||
injector: Injector,
|
||||
angularDelegate: AngularDelegate,
|
||||
protected z: NgZone
|
||||
protected z: NgZone,
|
||||
c: ChangeDetectorRef
|
||||
) {
|
||||
c.detach();
|
||||
this.el = ref.nativeElement;
|
||||
ref.nativeElement.delegate = angularDelegate.create(environmentInjector, injector);
|
||||
proxyOutputs(this, this.el, ['ionNavDidChange', 'ionNavWillChange']);
|
||||
@@ -27,12 +27,12 @@ export { IonModal } from './overlays/modal';
|
||||
export { IonRouterOutlet, provideComponentInputBinding } from './directives/navigation/router-outlet';
|
||||
export type { StackEvent } from './directives/navigation/stack-utils';
|
||||
|
||||
export { IonBackButtonDelegate } from './directives/navigation/back-button';
|
||||
export { IonBackButton } from './directives/navigation/back-button';
|
||||
export {
|
||||
RouterLinkDelegateDirective,
|
||||
RouterLinkWithHrefDelegateDirective,
|
||||
} from './directives/navigation/router-link-delegate';
|
||||
export { NavDelegate } from './directives/navigation/nav-delegate';
|
||||
export { IonNav } from './directives/navigation/nav';
|
||||
export { IonTabs } from './directives/navigation/tabs';
|
||||
|
||||
export { ProxyCmp } from './utils/proxy';
|
||||
|
||||
@@ -1,20 +1,23 @@
|
||||
import { Directive, Optional, ElementRef, NgZone } from '@angular/core';
|
||||
import { IonBackButtonDelegate as IonBackButtonDelegateBase, NavController, Config } from '@ionic/angular/common';
|
||||
import { Optional, ElementRef, NgZone, ChangeDetectorRef, Component, ChangeDetectionStrategy } from '@angular/core';
|
||||
import { IonBackButton as IonBackButtonBase, NavController, Config } from '@ionic/angular/common';
|
||||
|
||||
import { IonRouterOutlet } from './ion-router-outlet';
|
||||
|
||||
@Directive({
|
||||
@Component({
|
||||
selector: 'ion-back-button',
|
||||
template: '<ng-content></ng-content>',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
// eslint-disable-next-line @angular-eslint/directive-class-suffix
|
||||
export class IonBackButtonDelegateDirective extends IonBackButtonDelegateBase {
|
||||
export class IonBackButton extends IonBackButtonBase {
|
||||
constructor(
|
||||
@Optional() routerOutlet: IonRouterOutlet,
|
||||
navCtrl: NavController,
|
||||
config: Config,
|
||||
r: ElementRef,
|
||||
z: NgZone
|
||||
z: NgZone,
|
||||
c: ChangeDetectorRef
|
||||
) {
|
||||
super(routerOutlet, navCtrl, config, r, z);
|
||||
super(routerOutlet, navCtrl, config, r, z, c);
|
||||
}
|
||||
}
|
||||
|
||||
29
packages/angular/src/directives/navigation/ion-nav.ts
Normal file
29
packages/angular/src/directives/navigation/ion-nav.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import {
|
||||
ElementRef,
|
||||
Injector,
|
||||
EnvironmentInjector,
|
||||
NgZone,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
ChangeDetectionStrategy,
|
||||
} from '@angular/core';
|
||||
import { IonNav as IonNavBase, AngularDelegate } from '@ionic/angular/common';
|
||||
|
||||
@Component({
|
||||
selector: 'ion-nav',
|
||||
template: '<ng-content></ng-content>',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
// eslint-disable-next-line @angular-eslint/directive-class-suffix
|
||||
export class IonNav extends IonNavBase {
|
||||
constructor(
|
||||
ref: ElementRef,
|
||||
environmentInjector: EnvironmentInjector,
|
||||
injector: Injector,
|
||||
angularDelegate: AngularDelegate,
|
||||
z: NgZone,
|
||||
c: ChangeDetectorRef
|
||||
) {
|
||||
super(ref, environmentInjector, injector, angularDelegate, z, c);
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
import { Directive, ElementRef, Injector, EnvironmentInjector, NgZone } from '@angular/core';
|
||||
import { NavDelegate as NavDelegateBase, AngularDelegate } from '@ionic/angular/common';
|
||||
|
||||
@Directive({
|
||||
selector: 'ion-nav',
|
||||
})
|
||||
// eslint-disable-next-line @angular-eslint/directive-class-suffix
|
||||
export class NavDelegate extends NavDelegateBase {
|
||||
constructor(
|
||||
ref: ElementRef,
|
||||
environmentInjector: EnvironmentInjector,
|
||||
injector: Injector,
|
||||
angularDelegate: AngularDelegate,
|
||||
z: NgZone
|
||||
) {
|
||||
super(ref, environmentInjector, injector, angularDelegate, z);
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,6 @@ export const DIRECTIVES = [
|
||||
d.IonAlert,
|
||||
d.IonApp,
|
||||
d.IonAvatar,
|
||||
d.IonBackButton,
|
||||
d.IonBackdrop,
|
||||
d.IonBadge,
|
||||
d.IonBreadcrumb,
|
||||
@@ -50,7 +49,6 @@ export const DIRECTIVES = [
|
||||
d.IonMenu,
|
||||
d.IonMenuButton,
|
||||
d.IonMenuToggle,
|
||||
d.IonNav,
|
||||
d.IonNavLink,
|
||||
d.IonNote,
|
||||
d.IonPicker,
|
||||
|
||||
@@ -230,28 +230,6 @@ export class IonAvatar {
|
||||
export declare interface IonAvatar extends Components.IonAvatar {}
|
||||
|
||||
|
||||
@ProxyCmp({
|
||||
inputs: ['color', 'defaultHref', 'disabled', 'icon', 'mode', 'routerAnimation', 'text', 'type']
|
||||
})
|
||||
@Component({
|
||||
selector: 'ion-back-button',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
template: '<ng-content></ng-content>',
|
||||
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
|
||||
inputs: ['color', 'defaultHref', 'disabled', 'icon', 'mode', 'routerAnimation', 'text', 'type'],
|
||||
})
|
||||
export class IonBackButton {
|
||||
protected el: HTMLElement;
|
||||
constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) {
|
||||
c.detach();
|
||||
this.el = r.nativeElement;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export declare interface IonBackButton extends Components.IonBackButton {}
|
||||
|
||||
|
||||
@ProxyCmp({
|
||||
inputs: ['stopPropagation', 'tappable', 'visible']
|
||||
})
|
||||
@@ -1395,39 +1373,6 @@ export class IonMenuToggle {
|
||||
export declare interface IonMenuToggle extends Components.IonMenuToggle {}
|
||||
|
||||
|
||||
@ProxyCmp({
|
||||
inputs: ['animated', 'animation', 'root', 'rootParams', 'swipeGesture'],
|
||||
methods: ['push', 'insert', 'insertPages', 'pop', 'popTo', 'popToRoot', 'removeIndex', 'setRoot', 'setPages', 'getActive', 'getByIndex', 'canGoBack', 'getPrevious']
|
||||
})
|
||||
@Component({
|
||||
selector: 'ion-nav',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
template: '<ng-content></ng-content>',
|
||||
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
|
||||
inputs: ['animated', 'animation', 'root', 'rootParams', 'swipeGesture'],
|
||||
})
|
||||
export class IonNav {
|
||||
protected el: HTMLElement;
|
||||
constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) {
|
||||
c.detach();
|
||||
this.el = r.nativeElement;
|
||||
proxyOutputs(this, this.el, ['ionNavWillChange', 'ionNavDidChange']);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export declare interface IonNav extends Components.IonNav {
|
||||
/**
|
||||
* Event fired when the nav will change components
|
||||
*/
|
||||
ionNavWillChange: EventEmitter<CustomEvent<void>>;
|
||||
/**
|
||||
* Event fired when the nav has changed components
|
||||
*/
|
||||
ionNavDidChange: EventEmitter<CustomEvent<void>>;
|
||||
}
|
||||
|
||||
|
||||
@ProxyCmp({
|
||||
inputs: ['component', 'componentProps', 'routerAnimation', 'routerDirection']
|
||||
})
|
||||
|
||||
@@ -5,8 +5,8 @@ export { RadioValueAccessorDirective as RadioValueAccessor } from './directives/
|
||||
export { SelectValueAccessorDirective as SelectValueAccessor } from './directives/control-value-accessors/select-value-accessor';
|
||||
export { TextValueAccessorDirective as TextValueAccessor } from './directives/control-value-accessors/text-value-accessor';
|
||||
export { IonTabs } from './directives/navigation/ion-tabs';
|
||||
export { IonBackButtonDelegateDirective as IonBackButtonDelegate } from './directives/navigation/ion-back-button';
|
||||
export { NavDelegate } from './directives/navigation/nav-delegate';
|
||||
export { IonBackButton } from './directives/navigation/ion-back-button';
|
||||
export { IonNav } from './directives/navigation/ion-nav';
|
||||
export { IonRouterOutlet } from './directives/navigation/ion-router-outlet';
|
||||
export {
|
||||
RouterLinkDelegateDirective as RouterLinkDelegate,
|
||||
|
||||
@@ -17,10 +17,10 @@ import {
|
||||
SelectValueAccessorDirective,
|
||||
TextValueAccessorDirective,
|
||||
} from './directives/control-value-accessors';
|
||||
import { IonBackButtonDelegateDirective } from './directives/navigation/ion-back-button';
|
||||
import { IonBackButton } from './directives/navigation/ion-back-button';
|
||||
import { IonNav } from './directives/navigation/ion-nav';
|
||||
import { IonRouterOutlet } from './directives/navigation/ion-router-outlet';
|
||||
import { IonTabs } from './directives/navigation/ion-tabs';
|
||||
import { NavDelegate } from './directives/navigation/nav-delegate';
|
||||
import {
|
||||
RouterLinkDelegateDirective,
|
||||
RouterLinkWithHrefDelegateDirective,
|
||||
@@ -47,8 +47,8 @@ const DECLARATIONS = [
|
||||
// navigation
|
||||
IonTabs,
|
||||
IonRouterOutlet,
|
||||
IonBackButtonDelegateDirective,
|
||||
NavDelegate,
|
||||
IonBackButton,
|
||||
IonNav,
|
||||
RouterLinkDelegateDirective,
|
||||
RouterLinkWithHrefDelegateDirective,
|
||||
];
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/* eslint-disable */
|
||||
/* tslint:disable */
|
||||
import { fromEvent } from 'rxjs';
|
||||
|
||||
export const proxyInputs = (Cmp: any, inputs: string[]) => {
|
||||
const Prototype = Cmp.prototype;
|
||||
inputs.forEach((item) => {
|
||||
Object.defineProperty(Prototype, item, {
|
||||
get() {
|
||||
return this.el[item];
|
||||
},
|
||||
set(val: any) {
|
||||
this.z.runOutsideAngular(() => (this.el[item] = val));
|
||||
},
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export const proxyMethods = (Cmp: any, methods: string[]) => {
|
||||
const Prototype = Cmp.prototype;
|
||||
methods.forEach((methodName) => {
|
||||
Prototype[methodName] = function () {
|
||||
const args = arguments;
|
||||
return this.z.runOutsideAngular(() => this.el[methodName].apply(this.el, args));
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
export const proxyOutputs = (instance: any, el: any, events: string[]) => {
|
||||
events.forEach((eventName) => (instance[eventName] = fromEvent(el, eventName)));
|
||||
};
|
||||
|
||||
export const defineCustomElement = (tagName: string, customElement: any) => {
|
||||
if (customElement !== undefined && typeof customElements !== 'undefined' && !customElements.get(tagName)) {
|
||||
customElements.define(tagName, customElement);
|
||||
}
|
||||
};
|
||||
|
||||
// tslint:disable-next-line: only-arrow-functions
|
||||
export function ProxyCmp(opts: { defineCustomElementFn?: () => void; inputs?: any; methods?: any }) {
|
||||
const decorator = function (cls: any) {
|
||||
const { defineCustomElementFn, inputs, methods } = opts;
|
||||
|
||||
if (defineCustomElementFn !== undefined) {
|
||||
defineCustomElementFn();
|
||||
}
|
||||
|
||||
if (inputs) {
|
||||
proxyInputs(cls, inputs);
|
||||
}
|
||||
if (methods) {
|
||||
proxyMethods(cls, methods);
|
||||
}
|
||||
return cls;
|
||||
};
|
||||
return decorator;
|
||||
}
|
||||
24
packages/angular/standalone/src/directives/icon.ts
Normal file
24
packages/angular/standalone/src/directives/icon.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, NgZone } from '@angular/core';
|
||||
import { defineCustomElement as defineIonIcon } from 'ionicons/components/ion-icon.js';
|
||||
|
||||
import { ProxyCmp } from './angular-component-lib/utils';
|
||||
|
||||
@ProxyCmp({
|
||||
defineCustomElementFn: defineIonIcon,
|
||||
inputs: ['color', 'flipRtl', 'icon', 'ios', 'lazy', 'md', 'mode', 'name', 'sanitize', 'size', 'src'],
|
||||
})
|
||||
@Component({
|
||||
selector: 'ion-icon',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
template: '<ng-content></ng-content>',
|
||||
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
|
||||
inputs: ['color', 'flipRtl', 'icon', 'ios', 'lazy', 'md', 'mode', 'name', 'sanitize', 'size', 'src'],
|
||||
standalone: true,
|
||||
})
|
||||
export class IonIcon {
|
||||
protected el: HTMLElement;
|
||||
constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) {
|
||||
c.detach();
|
||||
this.el = r.nativeElement;
|
||||
}
|
||||
}
|
||||
3159
packages/angular/standalone/src/directives/proxies.ts
Normal file
3159
packages/angular/standalone/src/directives/proxies.ts
Normal file
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,6 @@ export { IonModal } from './overlays/modal';
|
||||
export { IonPopover } from './overlays/popover';
|
||||
export { IonRouterOutlet } from './navigation/router-outlet';
|
||||
export { IonRouterLink, IonRouterLinkWithHref } from './navigation/router-link-delegate';
|
||||
export { IonNav } from './navigation/nav-delegate';
|
||||
export { provideIonicAngular } from './providers/ionic-angular';
|
||||
export {
|
||||
ActionSheetController,
|
||||
@@ -23,3 +22,6 @@ export {
|
||||
NavParams,
|
||||
IonicRouteStrategy,
|
||||
} from '@ionic/angular/common';
|
||||
export { IonNav } from './navigation/nav';
|
||||
export { IonIcon } from './directives/icon';
|
||||
export * from './directives/proxies';
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
import { Component, Optional, ChangeDetectionStrategy, ElementRef, NgZone } from '@angular/core';
|
||||
import {
|
||||
IonBackButtonDelegate as IonBackButtonDelegateBase,
|
||||
NavController,
|
||||
Config,
|
||||
ProxyCmp,
|
||||
} from '@ionic/angular/common';
|
||||
import { Component, Optional, ChangeDetectionStrategy, ElementRef, NgZone, ChangeDetectorRef } from '@angular/core';
|
||||
import { IonBackButton as IonBackButtonBase, NavController, Config, ProxyCmp } from '@ionic/angular/common';
|
||||
import { defineCustomElement } from '@ionic/core/components/ion-back-button.js';
|
||||
|
||||
import { IonRouterOutlet } from './router-outlet';
|
||||
@@ -19,14 +14,15 @@ import { IonRouterOutlet } from './router-outlet';
|
||||
standalone: true,
|
||||
})
|
||||
// eslint-disable-next-line @angular-eslint/directive-class-suffix
|
||||
export class IonBackButton extends IonBackButtonDelegateBase {
|
||||
export class IonBackButton extends IonBackButtonBase {
|
||||
constructor(
|
||||
@Optional() routerOutlet: IonRouterOutlet,
|
||||
navCtrl: NavController,
|
||||
config: Config,
|
||||
r: ElementRef,
|
||||
z: NgZone
|
||||
z: NgZone,
|
||||
c: ChangeDetectorRef
|
||||
) {
|
||||
super(routerOutlet, navCtrl, config, r, z);
|
||||
super(routerOutlet, navCtrl, config, r, z, c);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Component, ElementRef, Injector, EnvironmentInjector, NgZone } from '@angular/core';
|
||||
import { NavDelegate as NavDelegateBase, ProxyCmp, AngularDelegate } from '@ionic/angular/common';
|
||||
import { Component, ElementRef, Injector, EnvironmentInjector, NgZone, ChangeDetectorRef } from '@angular/core';
|
||||
import { IonNav as IonNavBase, ProxyCmp, AngularDelegate } from '@ionic/angular/common';
|
||||
import { defineCustomElement } from '@ionic/core/components/ion-nav.js';
|
||||
|
||||
@ProxyCmp({
|
||||
@@ -10,14 +10,15 @@ import { defineCustomElement } from '@ionic/core/components/ion-nav.js';
|
||||
template: '<ng-content></ng-content>',
|
||||
standalone: true,
|
||||
})
|
||||
export class IonNav extends NavDelegateBase {
|
||||
export class IonNav extends IonNavBase {
|
||||
constructor(
|
||||
ref: ElementRef,
|
||||
environmentInjector: EnvironmentInjector,
|
||||
injector: Injector,
|
||||
angularDelegate: AngularDelegate,
|
||||
z: NgZone
|
||||
z: NgZone,
|
||||
c: ChangeDetectorRef
|
||||
) {
|
||||
super(ref, environmentInjector, injector, angularDelegate, z);
|
||||
super(ref, environmentInjector, injector, angularDelegate, z, c);
|
||||
}
|
||||
}
|
||||
@@ -1 +1,3 @@
|
||||
<ion-router-outlet></ion-router-outlet>
|
||||
<ion-app>
|
||||
<ion-router-outlet></ion-router-outlet>
|
||||
</ion-app>
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { IonRouterOutlet } from '@ionic/angular/standalone';
|
||||
import { IonRouterOutlet, IonApp } from '@ionic/angular/standalone';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root-standalone',
|
||||
templateUrl: './app.component.html',
|
||||
standalone: true,
|
||||
imports: [RouterModule, IonRouterOutlet]
|
||||
imports: [RouterModule, IonRouterOutlet, IonApp]
|
||||
})
|
||||
export class AppComponent {
|
||||
}
|
||||
|
||||
@@ -6,14 +6,15 @@ export const routes: Routes = [
|
||||
path: '',
|
||||
component: AppComponent,
|
||||
children: [
|
||||
{ path: 'popover', loadComponent: () => import('../popover/popover.component').then(m => m.PopoverComponent) },
|
||||
{ path: 'modal', loadComponent: () => import('../modal/modal.component').then(m => m.ModalComponent) },
|
||||
{ path: 'router-outlet', loadComponent: () => import('../router-outlet/router-outlet.component').then(m => m.RouterOutletComponent) },
|
||||
{ path: 'back-button', loadComponent: () => import('../back-button/back-button.component').then(m => m.BackButtonComponent) },
|
||||
{ path: 'router-link', loadComponent: () => import('../router-link/router-link.component').then(m => m.RouterLinkComponent) },
|
||||
{ path: 'nav', loadComponent: () => import('../nav/nav.component').then(m => m.NavComponent) },
|
||||
{ path: 'providers', loadComponent: () => import('../providers/providers.component').then(m => m.ProvidersComponent) },
|
||||
{ path: 'overlay-controllers', loadComponent: () => import('../overlay-controllers/overlay-controllers.component').then(m => m.OverlayControllersComponent) },
|
||||
{ path: 'popover', loadComponent: () => import('../popover/popover.component').then(c => c.PopoverComponent) },
|
||||
{ path: 'modal', loadComponent: () => import('../modal/modal.component').then(c => c.ModalComponent) },
|
||||
{ path: 'router-outlet', loadComponent: () => import('../router-outlet/router-outlet.component').then(c => c.RouterOutletComponent) },
|
||||
{ path: 'back-button', loadComponent: () => import('../back-button/back-button.component').then(c => c.BackButtonComponent) },
|
||||
{ path: 'router-link', loadComponent: () => import('../router-link/router-link.component').then(c => c.RouterLinkComponent) },
|
||||
{ path: 'nav', loadComponent: () => import('../nav/nav.component').then(c => c.NavComponent) },
|
||||
{ path: 'providers', loadComponent: () => import('../providers/providers.component').then(c => c.ProvidersComponent) },
|
||||
{ path: 'overlay-controllers', loadComponent: () => import('../overlay-controllers/overlay-controllers.component').then(c => c.OverlayControllersComponent) },
|
||||
{ path: 'button', loadComponent: () => import('../button/button.component').then(c => c.ButtonComponent) }
|
||||
]
|
||||
},
|
||||
];
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import { Component } from "@angular/core";
|
||||
import { IonButton } from '@ionic/angular/standalone';
|
||||
|
||||
@Component({
|
||||
selector: 'app-button',
|
||||
template: `<ion-button>Test</ion-button>`,
|
||||
standalone: true,
|
||||
imports: [IonButton]
|
||||
})
|
||||
export class ButtonComponent {
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user