Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions core/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@
"@playwright/test": "^1.62.1",
"@rollup/plugin-node-resolve": "^8.4.0",
"@rollup/plugin-virtual": "^2.0.3",
"@stencil/angular-output-target": "^1.4.1",
"@stencil/angular-output-target": "^1.5.0",
"@stencil/react-output-target": "^1.6.2",
"@stencil/sass": "^3.0.9",
"@stencil/vue-output-target": "0.14.2",
Expand Down
2 changes: 2 additions & 0 deletions core/stencil.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const getAngularOutputTargets = () => {
directivesArrayFile: '../packages/angular/src/lazy/directives/proxies-list.ts',
excludeComponents,
outputType: 'component',
booleanAttributes: true,
}),
angularOutputTarget({
componentCorePackage,
Expand Down Expand Up @@ -66,6 +67,7 @@ const getAngularOutputTargets = () => {
outputType: 'standalone',
// Emit each component in a separate file rather than putting them all in one large file.
esModules: true,
booleanAttributes: true,
})
];
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/* eslint-disable */
/* tslint:disable */

/**
* Transforms a value to a boolean so that boolean properties can be set by attribute presence,
* e.g. `<my-component disabled>` instead of `<my-component [disabled]="true">`.
*
* Strings are coerced the same way Angular's `booleanAttribute` coerces them, so `''` (a bare
* attribute) becomes `true` and `'false'` becomes `false`.
*
* Unlike Angular's `booleanAttribute`, `null` and `undefined` are passed through rather than
* coerced to `false`. Components frequently treat them as a state distinct from `false`:
*
* ```tsx
* // `undefined` means "decide based on the mode", which is not the same as `false`
* const showDetail = detail !== undefined ? detail : mode === 'ios';
*
* // a strict comparison also behaves differently for `null` than it does for `false`
* const showHandle = handle !== false;
* ```
*
* Both values reach inputs routinely in Angular templates, from the `async` pipe before its
* first emission and from form control values, so coercing them would change the behavior of
* bindings that work today.
*
* This is implemented here rather than imported from `@angular/core` so that consumers on
* Angular versions without `booleanAttribute` are unaffected by this file being generated.
*
* The parameter type is what Angular derives `ngAcceptInputType_*` from, so it decides which
* template bindings compile. Widening it to `unknown` would let any expression through.
*
* Declared as a function rather than an arrow constant because Angular has to resolve input
* transforms statically when compiling a library in partial compilation mode.
*
* This lives in its own file, separate from `utils.ts`, so that it carries no runtime imports.
* That keeps it independently type-checkable without pulling `rxjs` in for `proxyOutputs`.
*/
export function nullableBooleanAttribute(value: boolean | string | null | undefined): boolean | null | undefined {
if (value === null || value === undefined) {
return value;
}
return typeof value === 'boolean' ? value : value !== 'false';
}
115 changes: 58 additions & 57 deletions packages/angular/src/lazy/directives/proxies.ts

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/* eslint-disable */
/* tslint:disable */

/**
* Transforms a value to a boolean so that boolean properties can be set by attribute presence,
* e.g. `<my-component disabled>` instead of `<my-component [disabled]="true">`.
*
* Strings are coerced the same way Angular's `booleanAttribute` coerces them, so `''` (a bare
* attribute) becomes `true` and `'false'` becomes `false`.
*
* Unlike Angular's `booleanAttribute`, `null` and `undefined` are passed through rather than
* coerced to `false`. Components frequently treat them as a state distinct from `false`:
*
* ```tsx
* // `undefined` means "decide based on the mode", which is not the same as `false`
* const showDetail = detail !== undefined ? detail : mode === 'ios';
*
* // a strict comparison also behaves differently for `null` than it does for `false`
* const showHandle = handle !== false;
* ```
*
* Both values reach inputs routinely in Angular templates, from the `async` pipe before its
* first emission and from form control values, so coercing them would change the behavior of
* bindings that work today.
*
* This is implemented here rather than imported from `@angular/core` so that consumers on
* Angular versions without `booleanAttribute` are unaffected by this file being generated.
*
* The parameter type is what Angular derives `ngAcceptInputType_*` from, so it decides which
* template bindings compile. Widening it to `unknown` would let any expression through.
*
* Declared as a function rather than an arrow constant because Angular has to resolve input
* transforms statically when compiling a library in partial compilation mode.
*
* This lives in its own file, separate from `utils.ts`, so that it carries no runtime imports.
* That keeps it independently type-checkable without pulling `rxjs` in for `proxyOutputs`.
*/
export function nullableBooleanAttribute(value: boolean | string | null | undefined): boolean | null | undefined {
if (value === null || value === undefined) {
return value;
}
return typeof value === 'boolean' ? value : value !== 'false';
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, NgZone, EventEmitter, Output } from '@angular/core';

import { ProxyCmp } from './angular-component-lib/utils';
import { nullableBooleanAttribute } from './angular-component-lib/boolean-attribute';

import type { Components } from '@ionic/core/components';

Expand All @@ -17,7 +18,7 @@ import { defineCustomElement as defineIonAccordionGroup } from '@ionic/core/comp
changeDetection: ChangeDetectionStrategy.OnPush,
template: '<ng-content></ng-content>',
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
inputs: ['animated', 'disabled', 'expand', 'mode', 'multiple', 'readonly', 'value'],
inputs: [{ name: 'animated', transform: nullableBooleanAttribute }, { name: 'disabled', transform: nullableBooleanAttribute }, 'expand', 'mode', { name: 'multiple', transform: nullableBooleanAttribute }, { name: 'readonly', transform: nullableBooleanAttribute }, 'value'],
outputs: ['ionChange'],
})
export class IonAccordionGroup {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, NgZone } from '@angular/core';

import { ProxyCmp } from './angular-component-lib/utils';
import { nullableBooleanAttribute } from './angular-component-lib/boolean-attribute';

import type { Components } from '@ionic/core/components';

Expand All @@ -17,7 +18,7 @@ import { defineCustomElement as defineIonAccordion } from '@ionic/core/component
changeDetection: ChangeDetectionStrategy.OnPush,
template: '<ng-content></ng-content>',
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
inputs: ['disabled', 'mode', 'readonly', 'toggleIcon', 'toggleIconSlot', 'value'],
inputs: [{ name: 'disabled', transform: nullableBooleanAttribute }, 'mode', { name: 'readonly', transform: nullableBooleanAttribute }, 'toggleIcon', 'toggleIconSlot', 'value'],
})
export class IonAccordion {
protected el: HTMLIonAccordionElement;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, NgZone, EventEmitter, Output } from '@angular/core';

import { ProxyCmp } from './angular-component-lib/utils';
import { nullableBooleanAttribute } from './angular-component-lib/boolean-attribute';

import type { Components } from '@ionic/core/components';

Expand All @@ -18,7 +19,7 @@ import { defineCustomElement as defineIonActionSheet } from '@ionic/core/compone
changeDetection: ChangeDetectionStrategy.OnPush,
template: '<ng-content></ng-content>',
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
inputs: ['animated', 'backdropDismiss', 'buttons', 'cssClass', 'enterAnimation', 'header', 'htmlAttributes', 'isOpen', 'keyboardClose', 'leaveAnimation', 'mode', 'subHeader', 'translucent', 'trigger'],
inputs: [{ name: 'animated', transform: nullableBooleanAttribute }, { name: 'backdropDismiss', transform: nullableBooleanAttribute }, 'buttons', 'cssClass', 'enterAnimation', 'header', 'htmlAttributes', { name: 'isOpen', transform: nullableBooleanAttribute }, { name: 'keyboardClose', transform: nullableBooleanAttribute }, 'leaveAnimation', 'mode', 'subHeader', { name: 'translucent', transform: nullableBooleanAttribute }, 'trigger'],
outputs: ['ionActionSheetDidPresent', 'ionActionSheetWillPresent', 'ionActionSheetWillDismiss', 'ionActionSheetDidDismiss', 'didPresent', 'willPresent', 'willDismiss', 'didDismiss'],
})
export class IonActionSheet {
Expand Down
3 changes: 2 additions & 1 deletion packages/angular/src/standalone/directives/ion-alert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, NgZone, EventEmitter, Output } from '@angular/core';

import { ProxyCmp } from './angular-component-lib/utils';
import { nullableBooleanAttribute } from './angular-component-lib/boolean-attribute';

import type { Components } from '@ionic/core/components';

Expand All @@ -18,7 +19,7 @@ import { defineCustomElement as defineIonAlert } from '@ionic/core/components/io
changeDetection: ChangeDetectionStrategy.OnPush,
template: '<ng-content></ng-content>',
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
inputs: ['animated', 'backdropDismiss', 'buttons', 'cssClass', 'enterAnimation', 'header', 'htmlAttributes', 'inputs', 'isOpen', 'keyboardClose', 'leaveAnimation', 'message', 'mode', 'subHeader', 'translucent', 'trigger'],
inputs: [{ name: 'animated', transform: nullableBooleanAttribute }, { name: 'backdropDismiss', transform: nullableBooleanAttribute }, 'buttons', 'cssClass', 'enterAnimation', 'header', 'htmlAttributes', 'inputs', { name: 'isOpen', transform: nullableBooleanAttribute }, { name: 'keyboardClose', transform: nullableBooleanAttribute }, 'leaveAnimation', 'message', 'mode', 'subHeader', { name: 'translucent', transform: nullableBooleanAttribute }, 'trigger'],
outputs: ['ionAlertDidPresent', 'ionAlertWillPresent', 'ionAlertWillDismiss', 'ionAlertDidDismiss', 'didPresent', 'willPresent', 'willDismiss', 'didDismiss'],
})
export class IonAlert {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, NgZone, EventEmitter, Output } from '@angular/core';

import { ProxyCmp } from './angular-component-lib/utils';
import { nullableBooleanAttribute } from './angular-component-lib/boolean-attribute';

import type { Components } from '@ionic/core/components';

Expand All @@ -17,7 +18,7 @@ import { defineCustomElement as defineIonBackdrop } from '@ionic/core/components
changeDetection: ChangeDetectionStrategy.OnPush,
template: '<ng-content></ng-content>',
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
inputs: ['stopPropagation', 'tappable', 'visible'],
inputs: [{ name: 'stopPropagation', transform: nullableBooleanAttribute }, { name: 'tappable', transform: nullableBooleanAttribute }, { name: 'visible', transform: nullableBooleanAttribute }],
outputs: ['ionBackdropTap'],
})
export class IonBackdrop {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, NgZone, EventEmitter, Output } from '@angular/core';

import { ProxyCmp } from './angular-component-lib/utils';
import { nullableBooleanAttribute } from './angular-component-lib/boolean-attribute';

import type { Components } from '@ionic/core/components';

Expand All @@ -17,7 +18,7 @@ import { defineCustomElement as defineIonBreadcrumb } from '@ionic/core/componen
changeDetection: ChangeDetectionStrategy.OnPush,
template: '<ng-content></ng-content>',
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
inputs: ['active', 'color', 'disabled', 'download', 'href', 'mode', 'rel', 'routerAnimation', 'routerDirection', 'separator', 'target'],
inputs: [{ name: 'active', transform: nullableBooleanAttribute }, 'color', { name: 'disabled', transform: nullableBooleanAttribute }, 'download', 'href', 'mode', 'rel', 'routerAnimation', 'routerDirection', { name: 'separator', transform: nullableBooleanAttribute }, 'target'],
outputs: ['ionFocus', 'ionBlur'],
})
export class IonBreadcrumb {
Expand Down
3 changes: 2 additions & 1 deletion packages/angular/src/standalone/directives/ion-button.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, NgZone, EventEmitter, Output } from '@angular/core';

import { ProxyCmp } from './angular-component-lib/utils';
import { nullableBooleanAttribute } from './angular-component-lib/boolean-attribute';

import type { Components } from '@ionic/core/components';

Expand All @@ -17,7 +18,7 @@ import { defineCustomElement as defineIonButton } from '@ionic/core/components/i
changeDetection: ChangeDetectionStrategy.OnPush,
template: '<ng-content></ng-content>',
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
inputs: ['buttonType', 'color', 'disabled', 'download', 'expand', 'fill', 'form', 'href', 'mode', 'rel', 'routerAnimation', 'routerDirection', 'shape', 'size', 'strong', 'target', 'type'],
inputs: ['buttonType', 'color', { name: 'disabled', transform: nullableBooleanAttribute }, 'download', 'expand', 'fill', 'form', 'href', 'mode', 'rel', 'routerAnimation', 'routerDirection', 'shape', 'size', { name: 'strong', transform: nullableBooleanAttribute }, 'target', 'type'],
outputs: ['ionFocus', 'ionBlur'],
})
export class IonButton {
Expand Down
3 changes: 2 additions & 1 deletion packages/angular/src/standalone/directives/ion-buttons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, NgZone } from '@angular/core';

import { ProxyCmp } from './angular-component-lib/utils';
import { nullableBooleanAttribute } from './angular-component-lib/boolean-attribute';

import type { Components } from '@ionic/core/components';

Expand All @@ -17,7 +18,7 @@ import { defineCustomElement as defineIonButtons } from '@ionic/core/components/
changeDetection: ChangeDetectionStrategy.OnPush,
template: '<ng-content></ng-content>',
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
inputs: ['collapse'],
inputs: [{ name: 'collapse', transform: nullableBooleanAttribute }],
})
export class IonButtons {
protected el: HTMLIonButtonsElement;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, NgZone } from '@angular/core';

import { ProxyCmp } from './angular-component-lib/utils';
import { nullableBooleanAttribute } from './angular-component-lib/boolean-attribute';

import type { Components } from '@ionic/core/components';

Expand All @@ -17,7 +18,7 @@ import { defineCustomElement as defineIonCardHeader } from '@ionic/core/componen
changeDetection: ChangeDetectionStrategy.OnPush,
template: '<ng-content></ng-content>',
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
inputs: ['color', 'mode', 'translucent'],
inputs: ['color', 'mode', { name: 'translucent', transform: nullableBooleanAttribute }],
})
export class IonCardHeader {
protected el: HTMLIonCardHeaderElement;
Expand Down
3 changes: 2 additions & 1 deletion packages/angular/src/standalone/directives/ion-card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, NgZone } from '@angular/core';

import { ProxyCmp } from './angular-component-lib/utils';
import { nullableBooleanAttribute } from './angular-component-lib/boolean-attribute';

import type { Components } from '@ionic/core/components';

Expand All @@ -17,7 +18,7 @@ import { defineCustomElement as defineIonCard } from '@ionic/core/components/ion
changeDetection: ChangeDetectionStrategy.OnPush,
template: '<ng-content></ng-content>',
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
inputs: ['button', 'color', 'disabled', 'download', 'href', 'mode', 'rel', 'routerAnimation', 'routerDirection', 'target', 'type'],
inputs: [{ name: 'button', transform: nullableBooleanAttribute }, 'color', { name: 'disabled', transform: nullableBooleanAttribute }, 'download', 'href', 'mode', 'rel', 'routerAnimation', 'routerDirection', 'target', 'type'],
})
export class IonCard {
protected el: HTMLIonCardElement;
Expand Down
3 changes: 2 additions & 1 deletion packages/angular/src/standalone/directives/ion-chip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, NgZone } from '@angular/core';

import { ProxyCmp } from './angular-component-lib/utils';
import { nullableBooleanAttribute } from './angular-component-lib/boolean-attribute';

import type { Components } from '@ionic/core/components';

Expand All @@ -17,7 +18,7 @@ import { defineCustomElement as defineIonChip } from '@ionic/core/components/ion
changeDetection: ChangeDetectionStrategy.OnPush,
template: '<ng-content></ng-content>',
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
inputs: ['color', 'disabled', 'mode', 'outline'],
inputs: ['color', { name: 'disabled', transform: nullableBooleanAttribute }, 'mode', { name: 'outline', transform: nullableBooleanAttribute }],
})
export class IonChip {
protected el: HTMLIonChipElement;
Expand Down
3 changes: 2 additions & 1 deletion packages/angular/src/standalone/directives/ion-content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, NgZone, EventEmitter, Output } from '@angular/core';

import { ProxyCmp } from './angular-component-lib/utils';
import { nullableBooleanAttribute } from './angular-component-lib/boolean-attribute';

import type { Components } from '@ionic/core/components';

Expand All @@ -18,7 +19,7 @@ import { defineCustomElement as defineIonContent } from '@ionic/core/components/
changeDetection: ChangeDetectionStrategy.OnPush,
template: '<ng-content></ng-content>',
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
inputs: ['color', 'fixedSlotPlacement', 'forceOverscroll', 'fullscreen', 'scrollEvents', 'scrollX', 'scrollY'],
inputs: ['color', 'fixedSlotPlacement', { name: 'forceOverscroll', transform: nullableBooleanAttribute }, { name: 'fullscreen', transform: nullableBooleanAttribute }, { name: 'scrollEvents', transform: nullableBooleanAttribute }, { name: 'scrollX', transform: nullableBooleanAttribute }, { name: 'scrollY', transform: nullableBooleanAttribute }],
outputs: ['ionScrollStart', 'ionScroll', 'ionScrollEnd'],
})
export class IonContent {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, NgZone } from '@angular/core';

import { ProxyCmp } from './angular-component-lib/utils';
import { nullableBooleanAttribute } from './angular-component-lib/boolean-attribute';

import type { Components } from '@ionic/core/components';

Expand All @@ -17,7 +18,7 @@ import { defineCustomElement as defineIonDatetimeButton } from '@ionic/core/comp
changeDetection: ChangeDetectionStrategy.OnPush,
template: '<ng-content></ng-content>',
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
inputs: ['color', 'datetime', 'disabled', 'mode'],
inputs: ['color', 'datetime', { name: 'disabled', transform: nullableBooleanAttribute }, 'mode'],
})
export class IonDatetimeButton {
protected el: HTMLIonDatetimeButtonElement;
Expand Down
Loading
Loading