mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-16 10:01:59 +08:00
refactor(react): transition to Stencil React bindings (#23826)
This commit is contained in:
16
core/package-lock.json
generated
16
core/package-lock.json
generated
@ -18,6 +18,7 @@
|
|||||||
"@jest/core": "^26.6.3",
|
"@jest/core": "^26.6.3",
|
||||||
"@rollup/plugin-node-resolve": "^8.4.0",
|
"@rollup/plugin-node-resolve": "^8.4.0",
|
||||||
"@rollup/plugin-virtual": "^2.0.3",
|
"@rollup/plugin-virtual": "^2.0.3",
|
||||||
|
"@stencil/react-output-target": "^0.0.12",
|
||||||
"@stencil/sass": "1.3.2",
|
"@stencil/sass": "1.3.2",
|
||||||
"@stencil/vue-output-target": "^0.5.1",
|
"@stencil/vue-output-target": "^0.5.1",
|
||||||
"@types/jest": "^26.0.20",
|
"@types/jest": "^26.0.20",
|
||||||
@ -1367,6 +1368,15 @@
|
|||||||
"npm": ">=6.0.0"
|
"npm": ">=6.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@stencil/react-output-target": {
|
||||||
|
"version": "0.0.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/@stencil/react-output-target/-/react-output-target-0.0.12.tgz",
|
||||||
|
"integrity": "sha512-X/lWAI/FW4tg/pjwe5UWy8KbRk2vWcWR+S6tBqNzKO6pKD6qr60dfajN13EO9nnm5hGr48FP1m/M8kqFbjpZrg==",
|
||||||
|
"dev": true,
|
||||||
|
"peerDependencies": {
|
||||||
|
"@stencil/core": ">=1.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@stencil/sass": {
|
"node_modules/@stencil/sass": {
|
||||||
"version": "1.3.2",
|
"version": "1.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/@stencil/sass/-/sass-1.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/@stencil/sass/-/sass-1.3.2.tgz",
|
||||||
@ -15010,6 +15020,12 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.6.0.tgz",
|
||||||
"integrity": "sha512-QsxWayZyusnqSZrlCl81R71rA3KqFjVVQSH4E0rGN15F1GdQaFonKlHLyCOLKLig1zzC+DQkLLiUuocexuvdeQ=="
|
"integrity": "sha512-QsxWayZyusnqSZrlCl81R71rA3KqFjVVQSH4E0rGN15F1GdQaFonKlHLyCOLKLig1zzC+DQkLLiUuocexuvdeQ=="
|
||||||
},
|
},
|
||||||
|
"@stencil/react-output-target": {
|
||||||
|
"version": "0.0.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/@stencil/react-output-target/-/react-output-target-0.0.12.tgz",
|
||||||
|
"integrity": "sha512-X/lWAI/FW4tg/pjwe5UWy8KbRk2vWcWR+S6tBqNzKO6pKD6qr60dfajN13EO9nnm5hGr48FP1m/M8kqFbjpZrg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@stencil/sass": {
|
"@stencil/sass": {
|
||||||
"version": "1.3.2",
|
"version": "1.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/@stencil/sass/-/sass-1.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/@stencil/sass/-/sass-1.3.2.tgz",
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
"@jest/core": "^26.6.3",
|
"@jest/core": "^26.6.3",
|
||||||
"@rollup/plugin-node-resolve": "^8.4.0",
|
"@rollup/plugin-node-resolve": "^8.4.0",
|
||||||
"@rollup/plugin-virtual": "^2.0.3",
|
"@rollup/plugin-virtual": "^2.0.3",
|
||||||
|
"@stencil/react-output-target": "^0.0.12",
|
||||||
"@stencil/sass": "1.3.2",
|
"@stencil/sass": "1.3.2",
|
||||||
"@stencil/vue-output-target": "^0.5.1",
|
"@stencil/vue-output-target": "^0.5.1",
|
||||||
"@types/jest": "^26.0.20",
|
"@types/jest": "^26.0.20",
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { Config } from '@stencil/core';
|
import { Config } from '@stencil/core';
|
||||||
import { sass } from '@stencil/sass';
|
import { sass } from '@stencil/sass';
|
||||||
import { vueOutputTarget } from '@stencil/vue-output-target';
|
import { vueOutputTarget } from '@stencil/vue-output-target';
|
||||||
|
import { reactOutputTarget } from '@stencil/react-output-target';
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import { apiSpecGenerator } from './scripts/api-spec-generator';
|
import { apiSpecGenerator } from './scripts/api-spec-generator';
|
||||||
@ -61,6 +62,40 @@ export const config: Config = {
|
|||||||
})
|
})
|
||||||
],
|
],
|
||||||
outputTargets: [
|
outputTargets: [
|
||||||
|
reactOutputTarget({
|
||||||
|
componentCorePackage: '@ionic/core',
|
||||||
|
includePolyfills: false,
|
||||||
|
includeDefineCustomElements: false,
|
||||||
|
proxiesFile: '../packages/react/src/components/proxies.ts',
|
||||||
|
excludeComponents: [
|
||||||
|
// Routing
|
||||||
|
'ion-router',
|
||||||
|
'ion-route',
|
||||||
|
'ion-route-redirect',
|
||||||
|
'ion-router-link',
|
||||||
|
'ion-router-outlet',
|
||||||
|
'ion-back-button',
|
||||||
|
'ion-tab-button',
|
||||||
|
'ion-tabs',
|
||||||
|
'ion-tab-bar',
|
||||||
|
'ion-button',
|
||||||
|
'ion-card',
|
||||||
|
'ion-fab-button',
|
||||||
|
'ion-item',
|
||||||
|
'ion-item-option',
|
||||||
|
|
||||||
|
// Overlays
|
||||||
|
'ion-action-sheet',
|
||||||
|
'ion-alert',
|
||||||
|
'ion-loading',
|
||||||
|
'ion-modal',
|
||||||
|
'ion-picker',
|
||||||
|
'ion-popover',
|
||||||
|
'ion-toast',
|
||||||
|
|
||||||
|
'ion-icon'
|
||||||
|
]
|
||||||
|
}),
|
||||||
vueOutputTarget({
|
vueOutputTarget({
|
||||||
componentCorePackage: '@ionic/core',
|
componentCorePackage: '@ionic/core',
|
||||||
includeImportCustomElements: true,
|
includeImportCustomElements: true,
|
||||||
|
15
packages/react-router/test-app/package-lock.json
generated
15
packages/react-router/test-app/package-lock.json
generated
@ -77,7 +77,7 @@
|
|||||||
"style-loader": "0.23.1",
|
"style-loader": "0.23.1",
|
||||||
"terser-webpack-plugin": "2.3.4",
|
"terser-webpack-plugin": "2.3.4",
|
||||||
"ts-pnp": "1.1.5",
|
"ts-pnp": "1.1.5",
|
||||||
"typescript": "3.7.4",
|
"typescript": "^3.9.5",
|
||||||
"url-loader": "2.3.0",
|
"url-loader": "2.3.0",
|
||||||
"wait-on": "^5.3.0",
|
"wait-on": "^5.3.0",
|
||||||
"webpack": "4.41.5",
|
"webpack": "4.41.5",
|
||||||
@ -19603,9 +19603,10 @@
|
|||||||
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
|
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
|
||||||
},
|
},
|
||||||
"node_modules/typescript": {
|
"node_modules/typescript": {
|
||||||
"version": "3.7.4",
|
"version": "3.9.10",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.4.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz",
|
||||||
"integrity": "sha512-A25xv5XCtarLwXpcDNZzCGvW2D1S3/bACratYBx2sax8PefsFhlYmkQicKHvpYflFS8if4zne5zT5kpJ7pzuvw==",
|
"integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
"bin": {
|
"bin": {
|
||||||
"tsc": "bin/tsc",
|
"tsc": "bin/tsc",
|
||||||
"tsserver": "bin/tsserver"
|
"tsserver": "bin/tsserver"
|
||||||
@ -37499,9 +37500,9 @@
|
|||||||
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
|
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
|
||||||
},
|
},
|
||||||
"typescript": {
|
"typescript": {
|
||||||
"version": "3.7.4",
|
"version": "3.9.10",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.4.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz",
|
||||||
"integrity": "sha512-A25xv5XCtarLwXpcDNZzCGvW2D1S3/bACratYBx2sax8PefsFhlYmkQicKHvpYflFS8if4zne5zT5kpJ7pzuvw=="
|
"integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q=="
|
||||||
},
|
},
|
||||||
"undefsafe": {
|
"undefsafe": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
|
@ -72,7 +72,7 @@
|
|||||||
"style-loader": "0.23.1",
|
"style-loader": "0.23.1",
|
||||||
"terser-webpack-plugin": "2.3.4",
|
"terser-webpack-plugin": "2.3.4",
|
||||||
"ts-pnp": "1.1.5",
|
"ts-pnp": "1.1.5",
|
||||||
"typescript": "3.7.4",
|
"typescript": "^3.9.5",
|
||||||
"url-loader": "2.3.0",
|
"url-loader": "2.3.0",
|
||||||
"wait-on": "^5.3.0",
|
"wait-on": "^5.3.0",
|
||||||
"webpack": "4.41.5",
|
"webpack": "4.41.5",
|
||||||
|
@ -4,8 +4,8 @@ import { NavContext } from '../contexts/NavContext';
|
|||||||
|
|
||||||
import { IonicReactProps } from './IonicReactProps';
|
import { IonicReactProps } from './IonicReactProps';
|
||||||
import { IonIconInner } from './inner-proxies';
|
import { IonIconInner } from './inner-proxies';
|
||||||
|
import { deprecationWarning } from './react-component-lib/utils/dev';
|
||||||
import { createForwardRef, isPlatform } from './utils';
|
import { createForwardRef, isPlatform } from './utils';
|
||||||
import { deprecationWarning } from './utils/dev';
|
|
||||||
|
|
||||||
interface IonIconProps {
|
interface IonIconProps {
|
||||||
ariaLabel?: string;
|
ariaLabel?: string;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { JSX } from '@ionic/core';
|
import { JSX } from '@ionic/core';
|
||||||
import { createReactComponent } from '../createComponent';
|
import { createReactComponent } from '../react-component-lib';
|
||||||
import { render, fireEvent, cleanup, RenderResult } from '@testing-library/react';
|
import { render, fireEvent, cleanup, RenderResult } from '@testing-library/react';
|
||||||
import { IonButton } from '../index';
|
import { IonButton } from '../index';
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import * as utils from '../utils';
|
import * as utils from '../react-component-lib/utils';
|
||||||
import '@testing-library/jest-dom/extend-expect';
|
import '@testing-library/jest-dom/extend-expect';
|
||||||
|
|
||||||
describe('isCoveredByReact', () => {
|
describe('isCoveredByReact', () => {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { OverlayEventDetail } from '@ionic/core';
|
import { OverlayEventDetail } from '@ionic/core';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { attachProps, setRef } from './utils';
|
import { attachProps, setRef } from './react-component-lib/utils';
|
||||||
|
|
||||||
interface OverlayBase extends HTMLElement {
|
interface OverlayBase extends HTMLElement {
|
||||||
present: () => Promise<void>;
|
present: () => Promise<void>;
|
||||||
|
@ -4,10 +4,12 @@ import React from 'react';
|
|||||||
import {
|
import {
|
||||||
attachProps,
|
attachProps,
|
||||||
camelToDashCase,
|
camelToDashCase,
|
||||||
createForwardRef,
|
|
||||||
dashToPascalCase,
|
dashToPascalCase,
|
||||||
isCoveredByReact,
|
isCoveredByReact,
|
||||||
mergeRefs,
|
mergeRefs,
|
||||||
|
} from './react-component-lib/utils';
|
||||||
|
import {
|
||||||
|
createForwardRef
|
||||||
} from './utils';
|
} from './utils';
|
||||||
|
|
||||||
type InlineOverlayState = {
|
type InlineOverlayState = {
|
||||||
|
@ -2,7 +2,7 @@ import { OverlayEventDetail } from '@ionic/core';
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
|
|
||||||
import { attachProps, setRef } from './utils';
|
import { attachProps, setRef } from './react-component-lib/utils';
|
||||||
|
|
||||||
interface OverlayElement extends HTMLElement {
|
interface OverlayElement extends HTMLElement {
|
||||||
present: () => Promise<void>;
|
present: () => Promise<void>;
|
||||||
|
@ -8,10 +8,12 @@ import { RouterDirection } from '../models/RouterDirection';
|
|||||||
import {
|
import {
|
||||||
attachProps,
|
attachProps,
|
||||||
camelToDashCase,
|
camelToDashCase,
|
||||||
createForwardRef,
|
|
||||||
dashToPascalCase,
|
dashToPascalCase,
|
||||||
isCoveredByReact,
|
isCoveredByReact,
|
||||||
mergeRefs,
|
mergeRefs,
|
||||||
|
} from './react-component-lib/utils';
|
||||||
|
import {
|
||||||
|
createForwardRef
|
||||||
} from './utils';
|
} from './utils';
|
||||||
|
|
||||||
interface IonicReactInternalProps<ElementType> extends React.HTMLAttributes<ElementType> {
|
interface IonicReactInternalProps<ElementType> extends React.HTMLAttributes<ElementType> {
|
||||||
@ -24,9 +26,8 @@ interface IonicReactInternalProps<ElementType> extends React.HTMLAttributes<Elem
|
|||||||
routerAnimation?: AnimationBuilder;
|
routerAnimation?: AnimationBuilder;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const createReactComponent = <PropType, ElementType>(
|
export const createRoutingComponent = <PropType, ElementType>(
|
||||||
tagName: string,
|
tagName: string
|
||||||
routerLinkComponent = false
|
|
||||||
) => {
|
) => {
|
||||||
const displayName = dashToPascalCase(tagName);
|
const displayName = dashToPascalCase(tagName);
|
||||||
const ReactComponent = class extends React.Component<IonicReactInternalProps<PropType>> {
|
const ReactComponent = class extends React.Component<IonicReactInternalProps<PropType>> {
|
||||||
@ -86,7 +87,6 @@ export const createReactComponent = <PropType, ElementType>(
|
|||||||
style,
|
style,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (routerLinkComponent) {
|
|
||||||
if (this.props.routerLink && !this.props.href) {
|
if (this.props.routerLink && !this.props.href) {
|
||||||
newProps.href = this.props.routerLink;
|
newProps.href = this.props.routerLink;
|
||||||
}
|
}
|
||||||
@ -101,7 +101,6 @@ export const createReactComponent = <PropType, ElementType>(
|
|||||||
} else {
|
} else {
|
||||||
newProps.onClick = this.handleClick;
|
newProps.onClick = this.handleClick;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return React.createElement(tagName, newProps, children);
|
return React.createElement(tagName, newProps, children);
|
||||||
}
|
}
|
@ -63,6 +63,7 @@ export {
|
|||||||
ToastButton
|
ToastButton
|
||||||
} from '@ionic/core';
|
} from '@ionic/core';
|
||||||
export * from './proxies';
|
export * from './proxies';
|
||||||
|
export * from './routing-proxies';
|
||||||
|
|
||||||
// createControllerComponent
|
// createControllerComponent
|
||||||
export { IonAlert } from './IonAlert';
|
export { IonAlert } from './IonAlert';
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { JSX } from '@ionic/core';
|
import { JSX } from '@ionic/core';
|
||||||
import { JSX as IoniconsJSX } from 'ionicons';
|
import { JSX as IoniconsJSX } from 'ionicons';
|
||||||
|
|
||||||
import { /*@__PURE__*/ createReactComponent } from './createComponent';
|
import { /*@__PURE__*/ createReactComponent } from './react-component-lib';
|
||||||
|
|
||||||
export const IonTabButtonInner = /*@__PURE__*/ createReactComponent<
|
export const IonTabButtonInner = /*@__PURE__*/ createReactComponent<
|
||||||
JSX.IonTabButton & { onIonTabButtonClick?: (e: CustomEvent) => void },
|
JSX.IonTabButton & { onIonTabButtonClick?: (e: CustomEvent) => void },
|
||||||
|
@ -1,255 +1,77 @@
|
|||||||
import { JSX } from '@ionic/core';
|
/* eslint-disable */
|
||||||
|
/* tslint:disable */
|
||||||
|
/* auto-generated react proxies */
|
||||||
|
import { createReactComponent } from './react-component-lib';
|
||||||
|
|
||||||
import { createReactComponent } from './createComponent';
|
import type { JSX } from '@ionic/core';
|
||||||
import { HrefProps } from './hrefprops';
|
|
||||||
|
|
||||||
// ionic/core
|
|
||||||
export const IonApp = /*@__PURE__*/ createReactComponent<JSX.IonApp, HTMLIonAppElement>('ion-app');
|
|
||||||
export const IonTab = /*@__PURE__*/ createReactComponent<JSX.IonTab, HTMLIonTabElement>('ion-tab');
|
export const IonAccordion = /*@__PURE__*/createReactComponent<JSX.IonAccordion, HTMLIonAccordionElement>('ion-accordion');
|
||||||
export const IonRouterLink = /*@__PURE__*/ createReactComponent<
|
export const IonAccordionGroup = /*@__PURE__*/createReactComponent<JSX.IonAccordionGroup, HTMLIonAccordionGroupElement>('ion-accordion-group');
|
||||||
HrefProps<JSX.IonRouterLink>,
|
export const IonApp = /*@__PURE__*/createReactComponent<JSX.IonApp, HTMLIonAppElement>('ion-app');
|
||||||
HTMLIonRouterLinkElement
|
export const IonAvatar = /*@__PURE__*/createReactComponent<JSX.IonAvatar, HTMLIonAvatarElement>('ion-avatar');
|
||||||
>('ion-router-link', true);
|
export const IonBackdrop = /*@__PURE__*/createReactComponent<JSX.IonBackdrop, HTMLIonBackdropElement>('ion-backdrop');
|
||||||
export const IonAccordion = /*@__PURE__*/ createReactComponent<JSX.IonAccordion, HTMLIonAccordionElement>(
|
export const IonBadge = /*@__PURE__*/createReactComponent<JSX.IonBadge, HTMLIonBadgeElement>('ion-badge');
|
||||||
'ion-accordion'
|
export const IonBreadcrumb = /*@__PURE__*/createReactComponent<JSX.IonBreadcrumb, HTMLIonBreadcrumbElement>('ion-breadcrumb');
|
||||||
);
|
export const IonBreadcrumbs = /*@__PURE__*/createReactComponent<JSX.IonBreadcrumbs, HTMLIonBreadcrumbsElement>('ion-breadcrumbs');
|
||||||
export const IonAccordionGroup = /*@__PURE__*/ createReactComponent<JSX.IonAccordionGroup, HTMLIonAccordionGroupElement>(
|
export const IonButtons = /*@__PURE__*/createReactComponent<JSX.IonButtons, HTMLIonButtonsElement>('ion-buttons');
|
||||||
'ion-accordion-group'
|
export const IonCardContent = /*@__PURE__*/createReactComponent<JSX.IonCardContent, HTMLIonCardContentElement>('ion-card-content');
|
||||||
);
|
export const IonCardHeader = /*@__PURE__*/createReactComponent<JSX.IonCardHeader, HTMLIonCardHeaderElement>('ion-card-header');
|
||||||
export const IonAvatar = /*@__PURE__*/ createReactComponent<JSX.IonAvatar, HTMLIonAvatarElement>(
|
export const IonCardSubtitle = /*@__PURE__*/createReactComponent<JSX.IonCardSubtitle, HTMLIonCardSubtitleElement>('ion-card-subtitle');
|
||||||
'ion-avatar'
|
export const IonCardTitle = /*@__PURE__*/createReactComponent<JSX.IonCardTitle, HTMLIonCardTitleElement>('ion-card-title');
|
||||||
);
|
export const IonCheckbox = /*@__PURE__*/createReactComponent<JSX.IonCheckbox, HTMLIonCheckboxElement>('ion-checkbox');
|
||||||
export const IonBackdrop = /*@__PURE__*/ createReactComponent<
|
export const IonChip = /*@__PURE__*/createReactComponent<JSX.IonChip, HTMLIonChipElement>('ion-chip');
|
||||||
JSX.IonBackdrop,
|
export const IonCol = /*@__PURE__*/createReactComponent<JSX.IonCol, HTMLIonColElement>('ion-col');
|
||||||
HTMLIonBackdropElement
|
export const IonContent = /*@__PURE__*/createReactComponent<JSX.IonContent, HTMLIonContentElement>('ion-content');
|
||||||
>('ion-backdrop');
|
export const IonDatetime = /*@__PURE__*/createReactComponent<JSX.IonDatetime, HTMLIonDatetimeElement>('ion-datetime');
|
||||||
export const IonBadge = /*@__PURE__*/ createReactComponent<JSX.IonBadge, HTMLIonBadgeElement>(
|
export const IonFab = /*@__PURE__*/createReactComponent<JSX.IonFab, HTMLIonFabElement>('ion-fab');
|
||||||
'ion-badge'
|
export const IonFabList = /*@__PURE__*/createReactComponent<JSX.IonFabList, HTMLIonFabListElement>('ion-fab-list');
|
||||||
);
|
export const IonFooter = /*@__PURE__*/createReactComponent<JSX.IonFooter, HTMLIonFooterElement>('ion-footer');
|
||||||
export const IonBreadcrumb = /*@__PURE__*/ createReactComponent<JSX.IonBreadcrumb, HTMLIonBreadcrumbElement>(
|
export const IonGrid = /*@__PURE__*/createReactComponent<JSX.IonGrid, HTMLIonGridElement>('ion-grid');
|
||||||
'ion-breadcrumb'
|
export const IonHeader = /*@__PURE__*/createReactComponent<JSX.IonHeader, HTMLIonHeaderElement>('ion-header');
|
||||||
);
|
export const IonImg = /*@__PURE__*/createReactComponent<JSX.IonImg, HTMLIonImgElement>('ion-img');
|
||||||
export const IonBreadcrumbs = /*@__PURE__*/ createReactComponent<JSX.IonBreadcrumbs, HTMLIonBreadcrumbsElement>(
|
export const IonInfiniteScroll = /*@__PURE__*/createReactComponent<JSX.IonInfiniteScroll, HTMLIonInfiniteScrollElement>('ion-infinite-scroll');
|
||||||
'ion-breadcrumbs'
|
export const IonInfiniteScrollContent = /*@__PURE__*/createReactComponent<JSX.IonInfiniteScrollContent, HTMLIonInfiniteScrollContentElement>('ion-infinite-scroll-content');
|
||||||
);
|
export const IonInput = /*@__PURE__*/createReactComponent<JSX.IonInput, HTMLIonInputElement>('ion-input');
|
||||||
export const IonButton = /*@__PURE__*/ createReactComponent<
|
export const IonItemDivider = /*@__PURE__*/createReactComponent<JSX.IonItemDivider, HTMLIonItemDividerElement>('ion-item-divider');
|
||||||
HrefProps<JSX.IonButton>,
|
export const IonItemGroup = /*@__PURE__*/createReactComponent<JSX.IonItemGroup, HTMLIonItemGroupElement>('ion-item-group');
|
||||||
HTMLIonButtonElement
|
export const IonItemOptions = /*@__PURE__*/createReactComponent<JSX.IonItemOptions, HTMLIonItemOptionsElement>('ion-item-options');
|
||||||
>('ion-button', true);
|
export const IonItemSliding = /*@__PURE__*/createReactComponent<JSX.IonItemSliding, HTMLIonItemSlidingElement>('ion-item-sliding');
|
||||||
export const IonButtons = /*@__PURE__*/ createReactComponent<JSX.IonButtons, HTMLIonButtonsElement>(
|
export const IonLabel = /*@__PURE__*/createReactComponent<JSX.IonLabel, HTMLIonLabelElement>('ion-label');
|
||||||
'ion-buttons'
|
export const IonList = /*@__PURE__*/createReactComponent<JSX.IonList, HTMLIonListElement>('ion-list');
|
||||||
);
|
export const IonListHeader = /*@__PURE__*/createReactComponent<JSX.IonListHeader, HTMLIonListHeaderElement>('ion-list-header');
|
||||||
export const IonCard = /*@__PURE__*/ createReactComponent<
|
export const IonMenu = /*@__PURE__*/createReactComponent<JSX.IonMenu, HTMLIonMenuElement>('ion-menu');
|
||||||
HrefProps<JSX.IonCard>,
|
export const IonMenuButton = /*@__PURE__*/createReactComponent<JSX.IonMenuButton, HTMLIonMenuButtonElement>('ion-menu-button');
|
||||||
HTMLIonCardElement
|
export const IonMenuToggle = /*@__PURE__*/createReactComponent<JSX.IonMenuToggle, HTMLIonMenuToggleElement>('ion-menu-toggle');
|
||||||
>('ion-card', true);
|
export const IonNav = /*@__PURE__*/createReactComponent<JSX.IonNav, HTMLIonNavElement>('ion-nav');
|
||||||
export const IonCardContent = /*@__PURE__*/ createReactComponent<
|
export const IonNavLink = /*@__PURE__*/createReactComponent<JSX.IonNavLink, HTMLIonNavLinkElement>('ion-nav-link');
|
||||||
JSX.IonCardContent,
|
export const IonNote = /*@__PURE__*/createReactComponent<JSX.IonNote, HTMLIonNoteElement>('ion-note');
|
||||||
HTMLIonCardContentElement
|
export const IonProgressBar = /*@__PURE__*/createReactComponent<JSX.IonProgressBar, HTMLIonProgressBarElement>('ion-progress-bar');
|
||||||
>('ion-card-content');
|
export const IonRadio = /*@__PURE__*/createReactComponent<JSX.IonRadio, HTMLIonRadioElement>('ion-radio');
|
||||||
export const IonCardHeader = /*@__PURE__*/ createReactComponent<
|
export const IonRadioGroup = /*@__PURE__*/createReactComponent<JSX.IonRadioGroup, HTMLIonRadioGroupElement>('ion-radio-group');
|
||||||
JSX.IonCardHeader,
|
export const IonRange = /*@__PURE__*/createReactComponent<JSX.IonRange, HTMLIonRangeElement>('ion-range');
|
||||||
HTMLIonCardHeaderElement
|
export const IonRefresher = /*@__PURE__*/createReactComponent<JSX.IonRefresher, HTMLIonRefresherElement>('ion-refresher');
|
||||||
>('ion-card-header');
|
export const IonRefresherContent = /*@__PURE__*/createReactComponent<JSX.IonRefresherContent, HTMLIonRefresherContentElement>('ion-refresher-content');
|
||||||
export const IonCardSubtitle = /*@__PURE__*/ createReactComponent<
|
export const IonReorder = /*@__PURE__*/createReactComponent<JSX.IonReorder, HTMLIonReorderElement>('ion-reorder');
|
||||||
JSX.IonCardSubtitle,
|
export const IonReorderGroup = /*@__PURE__*/createReactComponent<JSX.IonReorderGroup, HTMLIonReorderGroupElement>('ion-reorder-group');
|
||||||
HTMLIonCardSubtitleElement
|
export const IonRippleEffect = /*@__PURE__*/createReactComponent<JSX.IonRippleEffect, HTMLIonRippleEffectElement>('ion-ripple-effect');
|
||||||
>('ion-card-subtitle');
|
export const IonRow = /*@__PURE__*/createReactComponent<JSX.IonRow, HTMLIonRowElement>('ion-row');
|
||||||
export const IonCardTitle = /*@__PURE__*/ createReactComponent<
|
export const IonSearchbar = /*@__PURE__*/createReactComponent<JSX.IonSearchbar, HTMLIonSearchbarElement>('ion-searchbar');
|
||||||
JSX.IonCardTitle,
|
export const IonSegment = /*@__PURE__*/createReactComponent<JSX.IonSegment, HTMLIonSegmentElement>('ion-segment');
|
||||||
HTMLIonCardTitleElement
|
export const IonSegmentButton = /*@__PURE__*/createReactComponent<JSX.IonSegmentButton, HTMLIonSegmentButtonElement>('ion-segment-button');
|
||||||
>('ion-card-title');
|
export const IonSelect = /*@__PURE__*/createReactComponent<JSX.IonSelect, HTMLIonSelectElement>('ion-select');
|
||||||
export const IonCheckbox = /*@__PURE__*/ createReactComponent<
|
export const IonSelectOption = /*@__PURE__*/createReactComponent<JSX.IonSelectOption, HTMLIonSelectOptionElement>('ion-select-option');
|
||||||
JSX.IonCheckbox,
|
export const IonSkeletonText = /*@__PURE__*/createReactComponent<JSX.IonSkeletonText, HTMLIonSkeletonTextElement>('ion-skeleton-text');
|
||||||
HTMLIonCheckboxElement
|
export const IonSlide = /*@__PURE__*/createReactComponent<JSX.IonSlide, HTMLIonSlideElement>('ion-slide');
|
||||||
>('ion-checkbox');
|
export const IonSlides = /*@__PURE__*/createReactComponent<JSX.IonSlides, HTMLIonSlidesElement>('ion-slides');
|
||||||
export const IonCol = /*@__PURE__*/ createReactComponent<JSX.IonCol, HTMLIonColElement>('ion-col');
|
export const IonSpinner = /*@__PURE__*/createReactComponent<JSX.IonSpinner, HTMLIonSpinnerElement>('ion-spinner');
|
||||||
export const IonContent = /*@__PURE__*/ createReactComponent<JSX.IonContent, HTMLIonContentElement>(
|
export const IonSplitPane = /*@__PURE__*/createReactComponent<JSX.IonSplitPane, HTMLIonSplitPaneElement>('ion-split-pane');
|
||||||
'ion-content'
|
export const IonTab = /*@__PURE__*/createReactComponent<JSX.IonTab, HTMLIonTabElement>('ion-tab');
|
||||||
);
|
export const IonText = /*@__PURE__*/createReactComponent<JSX.IonText, HTMLIonTextElement>('ion-text');
|
||||||
export const IonChip = /*@__PURE__*/ createReactComponent<JSX.IonChip, HTMLIonChipElement>(
|
export const IonTextarea = /*@__PURE__*/createReactComponent<JSX.IonTextarea, HTMLIonTextareaElement>('ion-textarea');
|
||||||
'ion-chip'
|
export const IonThumbnail = /*@__PURE__*/createReactComponent<JSX.IonThumbnail, HTMLIonThumbnailElement>('ion-thumbnail');
|
||||||
);
|
export const IonTitle = /*@__PURE__*/createReactComponent<JSX.IonTitle, HTMLIonTitleElement>('ion-title');
|
||||||
export const IonDatetime = /*@__PURE__*/ createReactComponent<
|
export const IonToggle = /*@__PURE__*/createReactComponent<JSX.IonToggle, HTMLIonToggleElement>('ion-toggle');
|
||||||
JSX.IonDatetime,
|
export const IonToolbar = /*@__PURE__*/createReactComponent<JSX.IonToolbar, HTMLIonToolbarElement>('ion-toolbar');
|
||||||
HTMLIonDatetimeElement
|
export const IonVirtualScroll = /*@__PURE__*/createReactComponent<JSX.IonVirtualScroll, HTMLIonVirtualScrollElement>('ion-virtual-scroll');
|
||||||
>('ion-datetime');
|
|
||||||
export const IonFab = /*@__PURE__*/ createReactComponent<JSX.IonFab, HTMLIonFabElement>('ion-fab');
|
|
||||||
export const IonFabButton = /*@__PURE__*/ createReactComponent<
|
|
||||||
HrefProps<JSX.IonFabButton>,
|
|
||||||
HTMLIonFabButtonElement
|
|
||||||
>('ion-fab-button', true);
|
|
||||||
export const IonFabList = /*@__PURE__*/ createReactComponent<JSX.IonFabList, HTMLIonFabListElement>(
|
|
||||||
'ion-fab-list'
|
|
||||||
);
|
|
||||||
export const IonFooter = /*@__PURE__*/ createReactComponent<JSX.IonFooter, HTMLIonFooterElement>(
|
|
||||||
'ion-footer'
|
|
||||||
);
|
|
||||||
export const IonGrid = /*@__PURE__*/ createReactComponent<JSX.IonGrid, HTMLIonGridElement>(
|
|
||||||
'ion-grid'
|
|
||||||
);
|
|
||||||
export const IonHeader = /*@__PURE__*/ createReactComponent<JSX.IonHeader, HTMLIonHeaderElement>(
|
|
||||||
'ion-header'
|
|
||||||
);
|
|
||||||
export const IonImg = /*@__PURE__*/ createReactComponent<JSX.IonImg, HTMLIonImgElement>('ion-img');
|
|
||||||
export const IonInfiniteScroll = /*@__PURE__*/ createReactComponent<
|
|
||||||
JSX.IonInfiniteScroll,
|
|
||||||
HTMLIonInfiniteScrollElement
|
|
||||||
>('ion-infinite-scroll');
|
|
||||||
export const IonInfiniteScrollContent = /*@__PURE__*/ createReactComponent<
|
|
||||||
JSX.IonInfiniteScrollContent,
|
|
||||||
HTMLIonInfiniteScrollContentElement
|
|
||||||
>('ion-infinite-scroll-content');
|
|
||||||
export const IonInput = /*@__PURE__*/ createReactComponent<JSX.IonInput, HTMLIonInputElement>(
|
|
||||||
'ion-input'
|
|
||||||
);
|
|
||||||
export const IonItem = /*@__PURE__*/ createReactComponent<
|
|
||||||
HrefProps<JSX.IonItem>,
|
|
||||||
HTMLIonItemElement
|
|
||||||
>('ion-item', true);
|
|
||||||
export const IonItemDivider = /*@__PURE__*/ createReactComponent<
|
|
||||||
JSX.IonItemDivider,
|
|
||||||
HTMLIonItemDividerElement
|
|
||||||
>('ion-item-divider');
|
|
||||||
export const IonItemGroup = /*@__PURE__*/ createReactComponent<
|
|
||||||
JSX.IonItemGroup,
|
|
||||||
HTMLIonItemGroupElement
|
|
||||||
>('ion-item-group');
|
|
||||||
export const IonItemOption = /*@__PURE__*/ createReactComponent<
|
|
||||||
HrefProps<JSX.IonItemOption>,
|
|
||||||
HTMLIonItemOptionElement
|
|
||||||
>('ion-item-option', true);
|
|
||||||
export const IonItemOptions = /*@__PURE__*/ createReactComponent<
|
|
||||||
JSX.IonItemOptions,
|
|
||||||
HTMLIonItemOptionsElement
|
|
||||||
>('ion-item-options');
|
|
||||||
export const IonItemSliding = /*@__PURE__*/ createReactComponent<
|
|
||||||
JSX.IonItemSliding,
|
|
||||||
HTMLIonItemSlidingElement
|
|
||||||
>('ion-item-sliding');
|
|
||||||
export const IonLabel = /*@__PURE__*/ createReactComponent<JSX.IonLabel, HTMLIonLabelElement>(
|
|
||||||
'ion-label'
|
|
||||||
);
|
|
||||||
export const IonList = /*@__PURE__*/ createReactComponent<JSX.IonList, HTMLIonListElement>(
|
|
||||||
'ion-list'
|
|
||||||
);
|
|
||||||
export const IonListHeader = /*@__PURE__*/ createReactComponent<
|
|
||||||
JSX.IonListHeader,
|
|
||||||
HTMLIonListHeaderElement
|
|
||||||
>('ion-list-header');
|
|
||||||
export const IonMenu = /*@__PURE__*/ createReactComponent<JSX.IonMenu, HTMLIonMenuElement>(
|
|
||||||
'ion-menu'
|
|
||||||
);
|
|
||||||
export const IonMenuButton = /*@__PURE__*/ createReactComponent<
|
|
||||||
JSX.IonMenuButton,
|
|
||||||
HTMLIonMenuButtonElement
|
|
||||||
>('ion-menu-button');
|
|
||||||
export const IonMenuToggle = /*@__PURE__*/ createReactComponent<
|
|
||||||
JSX.IonMenuToggle,
|
|
||||||
HTMLIonMenuToggleElement
|
|
||||||
>('ion-menu-toggle');
|
|
||||||
export const IonNote = /*@__PURE__*/ createReactComponent<JSX.IonNote, HTMLIonNoteElement>(
|
|
||||||
'ion-note'
|
|
||||||
);
|
|
||||||
export const IonPickerColumn = /*@__PURE__*/ createReactComponent<
|
|
||||||
JSX.IonPickerColumn,
|
|
||||||
HTMLIonPickerColumnElement
|
|
||||||
>('ion-picker-column');
|
|
||||||
export const IonNav = /*@__PURE__*/ createReactComponent<JSX.IonNav, HTMLIonNavElement>('ion-nav');
|
|
||||||
export const IonProgressBar = /*@__PURE__*/ createReactComponent<
|
|
||||||
JSX.IonProgressBar,
|
|
||||||
HTMLIonProgressBarElement
|
|
||||||
>('ion-progress-bar');
|
|
||||||
export const IonRadio = /*@__PURE__*/ createReactComponent<JSX.IonRadio, HTMLIonRadioElement>(
|
|
||||||
'ion-radio'
|
|
||||||
);
|
|
||||||
export const IonRadioGroup = /*@__PURE__*/ createReactComponent<
|
|
||||||
JSX.IonRadioGroup,
|
|
||||||
HTMLIonRadioGroupElement
|
|
||||||
>('ion-radio-group');
|
|
||||||
export const IonRange = /*@__PURE__*/ createReactComponent<JSX.IonRange, HTMLIonRangeElement>(
|
|
||||||
'ion-range'
|
|
||||||
);
|
|
||||||
export const IonRefresher = /*@__PURE__*/ createReactComponent<
|
|
||||||
JSX.IonRefresher,
|
|
||||||
HTMLIonRefresherElement
|
|
||||||
>('ion-refresher');
|
|
||||||
export const IonRefresherContent = /*@__PURE__*/ createReactComponent<
|
|
||||||
JSX.IonRefresherContent,
|
|
||||||
HTMLIonRefresherContentElement
|
|
||||||
>('ion-refresher-content');
|
|
||||||
export const IonReorder = /*@__PURE__*/ createReactComponent<JSX.IonReorder, HTMLIonReorderElement>(
|
|
||||||
'ion-reorder'
|
|
||||||
);
|
|
||||||
export const IonReorderGroup = /*@__PURE__*/ createReactComponent<
|
|
||||||
JSX.IonReorderGroup,
|
|
||||||
HTMLIonReorderGroupElement
|
|
||||||
>('ion-reorder-group');
|
|
||||||
export const IonRippleEffect = /*@__PURE__*/ createReactComponent<
|
|
||||||
JSX.IonRippleEffect,
|
|
||||||
HTMLIonRippleEffectElement
|
|
||||||
>('ion-ripple-effect');
|
|
||||||
export const IonRow = /*@__PURE__*/ createReactComponent<JSX.IonRow, HTMLIonRowElement>('ion-row');
|
|
||||||
export const IonSearchbar = /*@__PURE__*/ createReactComponent<
|
|
||||||
JSX.IonSearchbar,
|
|
||||||
HTMLIonSearchbarElement
|
|
||||||
>('ion-searchbar');
|
|
||||||
export const IonSegment = /*@__PURE__*/ createReactComponent<JSX.IonSegment, HTMLIonSegmentElement>(
|
|
||||||
'ion-segment'
|
|
||||||
);
|
|
||||||
export const IonSegmentButton = /*@__PURE__*/ createReactComponent<
|
|
||||||
JSX.IonSegmentButton,
|
|
||||||
HTMLIonSegmentButtonElement
|
|
||||||
>('ion-segment-button');
|
|
||||||
export const IonSelect = /*@__PURE__*/ createReactComponent<JSX.IonSelect, HTMLIonSelectElement>(
|
|
||||||
'ion-select'
|
|
||||||
);
|
|
||||||
export const IonSelectOption = /*@__PURE__*/ createReactComponent<
|
|
||||||
JSX.IonSelectOption,
|
|
||||||
HTMLIonSelectOptionElement
|
|
||||||
>('ion-select-option');
|
|
||||||
export const IonSelectPopover = /*@__PURE__*/ createReactComponent<
|
|
||||||
JSX.IonSelectPopover,
|
|
||||||
HTMLIonSelectPopoverElement
|
|
||||||
>('ion-select-popover');
|
|
||||||
export const IonSkeletonText = /*@__PURE__*/ createReactComponent<
|
|
||||||
JSX.IonSkeletonText,
|
|
||||||
HTMLIonSkeletonTextElement
|
|
||||||
>('ion-skeleton-text');
|
|
||||||
export const IonSlide = /*@__PURE__*/ createReactComponent<JSX.IonSlide, HTMLIonSlideElement>(
|
|
||||||
'ion-slide'
|
|
||||||
);
|
|
||||||
export const IonSlides = /*@__PURE__*/ createReactComponent<JSX.IonSlides, HTMLIonSlidesElement>(
|
|
||||||
'ion-slides'
|
|
||||||
);
|
|
||||||
export const IonSpinner = /*@__PURE__*/ createReactComponent<JSX.IonSpinner, HTMLIonSpinnerElement>(
|
|
||||||
'ion-spinner'
|
|
||||||
);
|
|
||||||
export const IonSplitPane = /*@__PURE__*/ createReactComponent<
|
|
||||||
JSX.IonSplitPane,
|
|
||||||
HTMLIonSplitPaneElement
|
|
||||||
>('ion-split-pane');
|
|
||||||
export const IonText = /*@__PURE__*/ createReactComponent<JSX.IonText, HTMLIonTextElement>(
|
|
||||||
'ion-text'
|
|
||||||
);
|
|
||||||
export const IonTextarea = /*@__PURE__*/ createReactComponent<
|
|
||||||
JSX.IonTextarea,
|
|
||||||
HTMLIonTextareaElement
|
|
||||||
>('ion-textarea');
|
|
||||||
export const IonThumbnail = /*@__PURE__*/ createReactComponent<
|
|
||||||
JSX.IonThumbnail,
|
|
||||||
HTMLIonThumbnailElement
|
|
||||||
>('ion-thumbnail');
|
|
||||||
export const IonTitle = /*@__PURE__*/ createReactComponent<JSX.IonTitle, HTMLIonTitleElement>(
|
|
||||||
'ion-title'
|
|
||||||
);
|
|
||||||
export const IonToggle = /*@__PURE__*/ createReactComponent<JSX.IonToggle, HTMLIonToggleElement>(
|
|
||||||
'ion-toggle'
|
|
||||||
);
|
|
||||||
export const IonToolbar = /*@__PURE__*/ createReactComponent<JSX.IonToolbar, HTMLIonToolbarElement>(
|
|
||||||
'ion-toolbar'
|
|
||||||
);
|
|
||||||
export const IonVirtualScroll = /*@__PURE__*/ createReactComponent<
|
|
||||||
JSX.IonVirtualScroll,
|
|
||||||
HTMLIonVirtualScrollElement
|
|
||||||
>('ion-virtual-scroll');
|
|
||||||
|
@ -0,0 +1,93 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import {
|
||||||
|
attachProps,
|
||||||
|
createForwardRef,
|
||||||
|
dashToPascalCase,
|
||||||
|
isCoveredByReact,
|
||||||
|
mergeRefs,
|
||||||
|
} from './utils';
|
||||||
|
|
||||||
|
export interface HTMLStencilElement extends HTMLElement {
|
||||||
|
componentOnReady(): Promise<this>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface StencilReactInternalProps<ElementType> extends React.HTMLAttributes<ElementType> {
|
||||||
|
forwardedRef: React.RefObject<ElementType>;
|
||||||
|
ref?: React.Ref<any>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createReactComponent = <
|
||||||
|
PropType,
|
||||||
|
ElementType extends HTMLStencilElement,
|
||||||
|
ContextStateType = {},
|
||||||
|
ExpandedPropsTypes = {}
|
||||||
|
>(
|
||||||
|
tagName: string,
|
||||||
|
ReactComponentContext?: React.Context<ContextStateType>,
|
||||||
|
manipulatePropsFunction?: (
|
||||||
|
originalProps: StencilReactInternalProps<ElementType>,
|
||||||
|
propsToPass: any,
|
||||||
|
) => ExpandedPropsTypes,
|
||||||
|
) => {
|
||||||
|
const displayName = dashToPascalCase(tagName);
|
||||||
|
|
||||||
|
const ReactComponent = class extends React.Component<StencilReactInternalProps<ElementType>> {
|
||||||
|
componentEl!: ElementType;
|
||||||
|
|
||||||
|
setComponentElRef = (element: ElementType) => {
|
||||||
|
this.componentEl = element;
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(props: StencilReactInternalProps<ElementType>) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.componentDidUpdate(this.props);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate(prevProps: StencilReactInternalProps<ElementType>) {
|
||||||
|
attachProps(this.componentEl, this.props, prevProps);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { children, forwardedRef, style, className, ref, ...cProps } = this.props;
|
||||||
|
|
||||||
|
let propsToPass = Object.keys(cProps).reduce((acc, name) => {
|
||||||
|
if (name.indexOf('on') === 0 && name[2] === name[2].toUpperCase()) {
|
||||||
|
const eventName = name.substring(2).toLowerCase();
|
||||||
|
if (typeof document !== 'undefined' && isCoveredByReact(eventName)) {
|
||||||
|
(acc as any)[name] = (cProps as any)[name];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
(acc as any)[name] = (cProps as any)[name];
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
if (manipulatePropsFunction) {
|
||||||
|
propsToPass = manipulatePropsFunction(this.props, propsToPass);
|
||||||
|
}
|
||||||
|
|
||||||
|
const newProps: Omit<StencilReactInternalProps<ElementType>, 'forwardedRef'> = {
|
||||||
|
...propsToPass,
|
||||||
|
ref: mergeRefs(forwardedRef, this.setComponentElRef),
|
||||||
|
style,
|
||||||
|
};
|
||||||
|
|
||||||
|
return React.createElement(tagName, newProps, children);
|
||||||
|
}
|
||||||
|
|
||||||
|
static get displayName() {
|
||||||
|
return displayName;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// If context was passed to createReactComponent then conditionally add it to the Component Class
|
||||||
|
if (ReactComponentContext) {
|
||||||
|
ReactComponent.contextType = ReactComponentContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
return createForwardRef<PropType, ElementType>(ReactComponent, displayName);
|
||||||
|
};
|
@ -0,0 +1,152 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import ReactDOM from 'react-dom';
|
||||||
|
|
||||||
|
import { OverlayEventDetail } from './interfaces';
|
||||||
|
import { StencilReactForwardedRef, attachProps, setRef } from './utils';
|
||||||
|
|
||||||
|
interface OverlayElement extends HTMLElement {
|
||||||
|
present: () => Promise<void>;
|
||||||
|
dismiss: (data?: any, role?: string | undefined) => Promise<boolean>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ReactOverlayProps {
|
||||||
|
children?: React.ReactNode;
|
||||||
|
isOpen: boolean;
|
||||||
|
onDidDismiss?: (event: CustomEvent<OverlayEventDetail>) => void;
|
||||||
|
onDidPresent?: (event: CustomEvent<OverlayEventDetail>) => void;
|
||||||
|
onWillDismiss?: (event: CustomEvent<OverlayEventDetail>) => void;
|
||||||
|
onWillPresent?: (event: CustomEvent<OverlayEventDetail>) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createOverlayComponent = <
|
||||||
|
OverlayComponent extends object,
|
||||||
|
OverlayType extends OverlayElement
|
||||||
|
>(
|
||||||
|
displayName: string,
|
||||||
|
controller: { create: (options: any) => Promise<OverlayType> }
|
||||||
|
) => {
|
||||||
|
const didDismissEventName = `on${displayName}DidDismiss`;
|
||||||
|
const didPresentEventName = `on${displayName}DidPresent`;
|
||||||
|
const willDismissEventName = `on${displayName}WillDismiss`;
|
||||||
|
const willPresentEventName = `on${displayName}WillPresent`;
|
||||||
|
|
||||||
|
type Props = OverlayComponent &
|
||||||
|
ReactOverlayProps & {
|
||||||
|
forwardedRef?: StencilReactForwardedRef<OverlayType>;
|
||||||
|
};
|
||||||
|
|
||||||
|
let isDismissing = false;
|
||||||
|
|
||||||
|
class Overlay extends React.Component<Props> {
|
||||||
|
overlay?: OverlayType;
|
||||||
|
el!: HTMLDivElement;
|
||||||
|
|
||||||
|
constructor(props: Props) {
|
||||||
|
super(props);
|
||||||
|
if (typeof document !== 'undefined') {
|
||||||
|
this.el = document.createElement('div');
|
||||||
|
}
|
||||||
|
this.handleDismiss = this.handleDismiss.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
static get displayName() {
|
||||||
|
return displayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
if (this.props.isOpen) {
|
||||||
|
this.present();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
if (this.overlay) {
|
||||||
|
this.overlay.dismiss();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleDismiss(event: CustomEvent<OverlayEventDetail<any>>) {
|
||||||
|
if (this.props.onDidDismiss) {
|
||||||
|
this.props.onDidDismiss(event);
|
||||||
|
}
|
||||||
|
setRef(this.props.forwardedRef, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
shouldComponentUpdate(nextProps: Props) {
|
||||||
|
// Check if the overlay component is about to dismiss
|
||||||
|
if (this.overlay && nextProps.isOpen !== this.props.isOpen && nextProps.isOpen === false) {
|
||||||
|
isDismissing = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
async componentDidUpdate(prevProps: Props) {
|
||||||
|
if (this.overlay) {
|
||||||
|
attachProps(this.overlay, this.props, prevProps);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prevProps.isOpen !== this.props.isOpen && this.props.isOpen === true) {
|
||||||
|
this.present(prevProps);
|
||||||
|
}
|
||||||
|
if (this.overlay && prevProps.isOpen !== this.props.isOpen && this.props.isOpen === false) {
|
||||||
|
await this.overlay.dismiss();
|
||||||
|
isDismissing = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Now that the overlay is dismissed
|
||||||
|
* we need to render again so that any
|
||||||
|
* inner components will be unmounted
|
||||||
|
*/
|
||||||
|
this.forceUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async present(prevProps?: Props) {
|
||||||
|
const {
|
||||||
|
children,
|
||||||
|
isOpen,
|
||||||
|
onDidDismiss,
|
||||||
|
onDidPresent,
|
||||||
|
onWillDismiss,
|
||||||
|
onWillPresent,
|
||||||
|
...cProps
|
||||||
|
} = this.props;
|
||||||
|
const elementProps = {
|
||||||
|
...cProps,
|
||||||
|
ref: this.props.forwardedRef,
|
||||||
|
[didDismissEventName]: this.handleDismiss,
|
||||||
|
[didPresentEventName]: (e: CustomEvent) =>
|
||||||
|
this.props.onDidPresent && this.props.onDidPresent(e),
|
||||||
|
[willDismissEventName]: (e: CustomEvent) =>
|
||||||
|
this.props.onWillDismiss && this.props.onWillDismiss(e),
|
||||||
|
[willPresentEventName]: (e: CustomEvent) =>
|
||||||
|
this.props.onWillPresent && this.props.onWillPresent(e),
|
||||||
|
};
|
||||||
|
|
||||||
|
this.overlay = await controller.create({
|
||||||
|
...elementProps,
|
||||||
|
component: this.el,
|
||||||
|
componentProps: {},
|
||||||
|
});
|
||||||
|
|
||||||
|
setRef(this.props.forwardedRef, this.overlay);
|
||||||
|
attachProps(this.overlay, elementProps, prevProps);
|
||||||
|
|
||||||
|
await this.overlay.present();
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
/**
|
||||||
|
* Continue to render the component even when
|
||||||
|
* overlay is dismissing otherwise component
|
||||||
|
* will be hidden before animation is done.
|
||||||
|
*/
|
||||||
|
return ReactDOM.createPortal(this.props.isOpen || isDismissing ? this.props.children : null, this.el);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return React.forwardRef<OverlayType, Props>((props, ref) => {
|
||||||
|
return <Overlay {...props} forwardedRef={ref} />;
|
||||||
|
});
|
||||||
|
};
|
@ -0,0 +1,2 @@
|
|||||||
|
export { createReactComponent } from './createComponent';
|
||||||
|
export { createOverlayComponent } from './createOverlayComponent';
|
@ -0,0 +1,34 @@
|
|||||||
|
// General types important to applications using stencil built components
|
||||||
|
export interface EventEmitter<T = any> {
|
||||||
|
emit: (data?: T) => CustomEvent<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface StyleReactProps {
|
||||||
|
class?: string;
|
||||||
|
className?: string;
|
||||||
|
style?: { [key: string]: any };
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OverlayEventDetail<T = any> {
|
||||||
|
data?: T;
|
||||||
|
role?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OverlayInterface {
|
||||||
|
el: HTMLElement;
|
||||||
|
animated: boolean;
|
||||||
|
keyboardClose: boolean;
|
||||||
|
overlayIndex: number;
|
||||||
|
presented: boolean;
|
||||||
|
|
||||||
|
enterAnimation?: any;
|
||||||
|
leaveAnimation?: any;
|
||||||
|
|
||||||
|
didPresent: EventEmitter<void>;
|
||||||
|
willPresent: EventEmitter<void>;
|
||||||
|
willDismiss: EventEmitter<OverlayEventDetail>;
|
||||||
|
didDismiss: EventEmitter<OverlayEventDetail>;
|
||||||
|
|
||||||
|
present(): Promise<void>;
|
||||||
|
dismiss(data?: any, role?: string): Promise<boolean>;
|
||||||
|
}
|
@ -28,11 +28,10 @@ export const attachProps = (node: HTMLElement, newProps: any, oldProps: any = {}
|
|||||||
syncEvent(node, eventNameLc, newProps[name]);
|
syncEvent(node, eventNameLc, newProps[name]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
(node as any)[name] = newProps[name];
|
||||||
const propType = typeof newProps[name];
|
const propType = typeof newProps[name];
|
||||||
if (propType === 'string') {
|
if (propType === 'string') {
|
||||||
node.setAttribute(camelToDashCase(name), newProps[name]);
|
node.setAttribute(camelToDashCase(name), newProps[name]);
|
||||||
} else {
|
|
||||||
(node as any)[name] = newProps[name];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
@ -0,0 +1,47 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import type { StyleReactProps } from '../interfaces';
|
||||||
|
|
||||||
|
export type StencilReactExternalProps<PropType, ElementType> = PropType &
|
||||||
|
Omit<React.HTMLAttributes<ElementType>, 'style'> &
|
||||||
|
StyleReactProps;
|
||||||
|
|
||||||
|
// This will be replaced with React.ForwardedRef when react-output-target is upgraded to React v17
|
||||||
|
export type StencilReactForwardedRef<T> = ((instance: T | null) => void) | React.MutableRefObject<T | null> | null;
|
||||||
|
|
||||||
|
export const setRef = (ref: StencilReactForwardedRef<any> | React.Ref<any> | undefined, value: any) => {
|
||||||
|
if (typeof ref === 'function') {
|
||||||
|
ref(value)
|
||||||
|
} else if (ref != null) {
|
||||||
|
// Cast as a MutableRef so we can assign current
|
||||||
|
(ref as React.MutableRefObject<any>).current = value
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const mergeRefs = (
|
||||||
|
...refs: (StencilReactForwardedRef<any> | React.Ref<any> | undefined)[]
|
||||||
|
): React.RefCallback<any> => {
|
||||||
|
return (value: any) => {
|
||||||
|
refs.forEach(ref => {
|
||||||
|
setRef(ref, value)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const createForwardRef = <PropType, ElementType>(
|
||||||
|
ReactComponent: any,
|
||||||
|
displayName: string,
|
||||||
|
) => {
|
||||||
|
const forwardRef = (
|
||||||
|
props: StencilReactExternalProps<PropType, ElementType>,
|
||||||
|
ref: StencilReactForwardedRef<ElementType>,
|
||||||
|
) => {
|
||||||
|
return <ReactComponent {...props} forwardedRef={ref} />;
|
||||||
|
};
|
||||||
|
forwardRef.displayName = displayName;
|
||||||
|
|
||||||
|
return React.forwardRef(forwardRef);
|
||||||
|
};
|
||||||
|
|
||||||
|
export * from './attachProps';
|
||||||
|
export * from './case';
|
34
packages/react/src/components/routing-proxies.ts
Normal file
34
packages/react/src/components/routing-proxies.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import type { JSX } from '@ionic/core';
|
||||||
|
|
||||||
|
import { createRoutingComponent } from './createRoutingComponent';
|
||||||
|
import { HrefProps } from './hrefprops';
|
||||||
|
|
||||||
|
export const IonRouterLink = /*@__PURE__*/ createRoutingComponent<
|
||||||
|
HrefProps<JSX.IonRouterLink>,
|
||||||
|
HTMLIonRouterLinkElement
|
||||||
|
>('ion-router-link');
|
||||||
|
|
||||||
|
export const IonButton = /*@__PURE__*/ createRoutingComponent<
|
||||||
|
HrefProps<JSX.IonButton>,
|
||||||
|
HTMLIonButtonElement
|
||||||
|
>('ion-button');
|
||||||
|
|
||||||
|
export const IonCard = /*@__PURE__*/ createRoutingComponent<
|
||||||
|
HrefProps<JSX.IonCard>,
|
||||||
|
HTMLIonCardElement
|
||||||
|
>('ion-card');
|
||||||
|
|
||||||
|
export const IonFabButton = /*@__PURE__*/ createRoutingComponent<
|
||||||
|
HrefProps<JSX.IonFabButton>,
|
||||||
|
HTMLIonFabButtonElement
|
||||||
|
>('ion-fab-button');
|
||||||
|
|
||||||
|
export const IonItem = /*@__PURE__*/ createRoutingComponent<
|
||||||
|
HrefProps<JSX.IonItem>,
|
||||||
|
HTMLIonItemElement
|
||||||
|
>('ion-item');
|
||||||
|
|
||||||
|
export const IonItemOption = /*@__PURE__*/ createRoutingComponent<
|
||||||
|
HrefProps<JSX.IonItemOption>,
|
||||||
|
HTMLIonItemOptionElement
|
||||||
|
>('ion-item-option');
|
@ -27,28 +27,6 @@ export const createForwardRef = <PropType, ElementType>(
|
|||||||
return React.forwardRef(forwardRef);
|
return React.forwardRef(forwardRef);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const setRef = (ref: React.ForwardedRef<any> | React.Ref<any> | undefined, value: any) => {
|
|
||||||
if (typeof ref === 'function') {
|
|
||||||
ref(value)
|
|
||||||
} else if (ref != null) {
|
|
||||||
// Cast as a MutableRef so we can assign current
|
|
||||||
(ref as React.MutableRefObject<any>).current = value
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const mergeRefs = (
|
|
||||||
...refs: (React.ForwardedRef<any> | React.Ref<any> | undefined)[]
|
|
||||||
): React.RefCallback<any> => {
|
|
||||||
return (value: any) => {
|
|
||||||
refs.forEach(ref => {
|
|
||||||
setRef(ref, value)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export * from './attachProps';
|
|
||||||
export * from './case';
|
|
||||||
|
|
||||||
export const isPlatform = (platform: Platforms) => {
|
export const isPlatform = (platform: Platforms) => {
|
||||||
return isPlatformCore(window, platform);
|
return isPlatformCore(window, platform);
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { OverlayEventDetail } from '@ionic/core';
|
import { OverlayEventDetail } from '@ionic/core';
|
||||||
import { useMemo, useRef } from 'react';
|
import { useMemo, useRef } from 'react';
|
||||||
|
|
||||||
import { attachProps } from '../components/utils';
|
import { attachProps } from '../components/react-component-lib/utils';
|
||||||
|
|
||||||
import { HookOverlayOptions } from './HookOverlayOptions';
|
import { HookOverlayOptions } from './HookOverlayOptions';
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ import { OverlayEventDetail } from '@ionic/core';
|
|||||||
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
|
|
||||||
import { attachProps } from '../components/utils';
|
import { attachProps } from '../components/react-component-lib/utils';
|
||||||
|
|
||||||
import { HookOverlayOptions } from './HookOverlayOptions';
|
import { HookOverlayOptions } from './HookOverlayOptions';
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { mergeRefs } from '../components/utils';
|
import { mergeRefs } from '../components/react-component-lib/utils';
|
||||||
import { IonLifeCycleContext } from '../contexts/IonLifeCycleContext';
|
import { IonLifeCycleContext } from '../contexts/IonLifeCycleContext';
|
||||||
import { RouteInfo } from '../models';
|
import { RouteInfo } from '../models';
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user