Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(react): Next.js Support #445

Merged
merged 40 commits into from
Aug 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
26d4728
feat(react-output-target): generate functional components and ES modu…
sean-perkins May 30, 2024
0d36721
exploration nextjs support
christian-bromann May 13, 2024
762e4f0
update Stencil with support for DSD
christian-bromann Jun 27, 2024
975bbd5
get rid of hydration errors
christian-bromann Jul 3, 2024
f9603cd
enhance output target
christian-bromann Jul 8, 2024
760dba9
add tests
christian-bromann Jul 9, 2024
780af73
fix dep
christian-bromann Jul 9, 2024
b6a8ab4
remove type property in package.json
christian-bromann Jul 9, 2024
edc08b1
remove hydrate dir
christian-bromann Jul 9, 2024
ceff657
move ssr support into custom export
christian-bromann Jul 9, 2024
44689ee
clear hydrate folder again
christian-bromann Jul 9, 2024
834d577
skip lib check
christian-bromann Jul 10, 2024
57f35ad
skip lib check
christian-bromann Jul 10, 2024
11dfcc0
better resolve light dom
christian-bromann Jul 12, 2024
005df51
remove unused import
christian-bromann Jul 12, 2024
1afa38f
match default dir with stencil
christian-bromann Jul 15, 2024
49ee9c0
more improvements on light dom rendering
christian-bromann Jul 15, 2024
fd81738
remove duplicate hydrate ot
christian-bromann Jul 16, 2024
7d4d7b8
remove style prop
christian-bromann Jul 16, 2024
2d31629
fail if outdir is not set
christian-bromann Jul 16, 2024
dbafadd
import hydration script and ssr runtime only within the server component
christian-bromann Jul 22, 2024
23b1659
validate hydrate output target to be set if hydrateModule option is set
christian-bromann Jul 22, 2024
48dff06
improve implementation
christian-bromann Jul 23, 2024
d06fb5d
separate files for server and client components
christian-bromann Jul 23, 2024
31afc30
properly create server and client side components
christian-bromann Jul 24, 2024
9663e57
don't parse children
christian-bromann Jul 25, 2024
4dc783c
use own runtime
christian-bromann Jul 25, 2024
1ef2008
validate that external runtime is set to 'true'
christian-bromann Jul 25, 2024
d9ab5b6
adjust test
christian-bromann Jul 29, 2024
20ea6cc
update Stencil dev build
christian-bromann Jul 29, 2024
3a463d2
recognise that externalRuntime default is true
christian-bromann Jul 31, 2024
f7d88e9
bring back light DOM rendering for better hydration results
christian-bromann Jul 31, 2024
9fbc202
revert light dom approach
christian-bromann Aug 1, 2024
f14121d
minor formatting
christian-bromann Aug 1, 2024
99c2fc3
update stencil
christian-bromann Aug 20, 2024
85edd55
explicitly type component exports
christian-bromann Aug 20, 2024
1d2791a
unit test tweak
christian-bromann Aug 20, 2024
5e4a31f
fix build
christian-bromann Aug 26, 2024
f5ae554
use latest Stencil release
christian-bromann Aug 27, 2024
6ae26e5
fix test
christian-bromann Aug 27, 2024
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ build/
.npmrc
*.tgz
*.lerna_backup
packages/example-project/component-library/hydrate
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
'use client';

/**
* This file was automatically generated by the Stencil React Output Target.
* Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
*/

/* eslint-disable */

import type { EventName } from '@stencil/react-output-target/runtime';
import type { EventName, StencilReactComponent } from '@stencil/react-output-target/runtime';
import { createComponent } from '@stencil/react-output-target/runtime';
import {
type CheckboxChangeEventDetail,
Expand Down Expand Up @@ -58,7 +60,10 @@ type MyButtonEvents = {
onMyBlur: EventName<CustomEvent<void>>;
};

export const MyButton = /*@__PURE__*/ createComponent<MyButtonElement, MyButtonEvents>({
export const MyButton: StencilReactComponent<MyButtonElement, MyButtonEvents> = /*@__PURE__*/ createComponent<
MyButtonElement,
MyButtonEvents
>({
tagName: 'my-button',
elementClass: MyButtonElement,
react: React,
Expand All @@ -75,7 +80,10 @@ type MyCheckboxEvents = {
onMyBlur: EventName<CustomEvent<void>>;
};

export const MyCheckbox = /*@__PURE__*/ createComponent<MyCheckboxElement, MyCheckboxEvents>({
export const MyCheckbox: StencilReactComponent<MyCheckboxElement, MyCheckboxEvents> = /*@__PURE__*/ createComponent<
MyCheckboxElement,
MyCheckboxEvents
>({
tagName: 'my-checkbox',
elementClass: MyCheckboxElement,
react: React,
Expand All @@ -89,7 +97,10 @@ export const MyCheckbox = /*@__PURE__*/ createComponent<MyCheckboxElement, MyChe

type MyComponentEvents = { onMyCustomEvent: EventName<CustomEvent<number>> };

export const MyComponent = /*@__PURE__*/ createComponent<MyComponentElement, MyComponentEvents>({
export const MyComponent: StencilReactComponent<MyComponentElement, MyComponentEvents> = /*@__PURE__*/ createComponent<
MyComponentElement,
MyComponentEvents
>({
tagName: 'my-component',
elementClass: MyComponentElement,
react: React,
Expand All @@ -104,7 +115,10 @@ type MyInputEvents = {
onMyFocus: EventName<CustomEvent<void>>;
};

export const MyInput = /*@__PURE__*/ createComponent<MyInputElement, MyInputEvents>({
export const MyInput: StencilReactComponent<MyInputElement, MyInputEvents> = /*@__PURE__*/ createComponent<
MyInputElement,
MyInputEvents
>({
tagName: 'my-input',
elementClass: MyInputElement,
react: React,
Expand All @@ -120,11 +134,14 @@ export const MyInput = /*@__PURE__*/ createComponent<MyInputElement, MyInputEven
type MyPopoverEvents = {
onMyPopoverDidPresent: EventName<CustomEvent<void>>;
onMyPopoverWillPresent: EventName<CustomEvent<void>>;
onMyPopoverWillDismiss: EventName<MyPopoverCustomEvent<OverlayEventDetail<any>>>;
onMyPopoverDidDismiss: EventName<MyPopoverCustomEvent<OverlayEventDetail<any>>>;
onMyPopoverWillDismiss: EventName<MyPopoverCustomEvent<OverlayEventDetail>>;
onMyPopoverDidDismiss: EventName<MyPopoverCustomEvent<OverlayEventDetail>>;
};

export const MyPopover = /*@__PURE__*/ createComponent<MyPopoverElement, MyPopoverEvents>({
export const MyPopover: StencilReactComponent<MyPopoverElement, MyPopoverEvents> = /*@__PURE__*/ createComponent<
MyPopoverElement,
MyPopoverEvents
>({
tagName: 'my-popover',
elementClass: MyPopoverElement,
react: React,
Expand All @@ -143,7 +160,10 @@ type MyRadioEvents = {
onMySelect: EventName<CustomEvent<void>>;
};

export const MyRadio = /*@__PURE__*/ createComponent<MyRadioElement, MyRadioEvents>({
export const MyRadio: StencilReactComponent<MyRadioElement, MyRadioEvents> = /*@__PURE__*/ createComponent<
MyRadioElement,
MyRadioEvents
>({
tagName: 'my-radio',
elementClass: MyRadioElement,
react: React,
Expand All @@ -157,21 +177,25 @@ export const MyRadio = /*@__PURE__*/ createComponent<MyRadioElement, MyRadioEven

type MyRadioGroupEvents = { onMyChange: EventName<MyRadioGroupCustomEvent<RadioGroupChangeEventDetail>> };

export const MyRadioGroup = /*@__PURE__*/ createComponent<MyRadioGroupElement, MyRadioGroupEvents>({
tagName: 'my-radio-group',
elementClass: MyRadioGroupElement,
react: React,
events: { onMyChange: 'myChange' } as MyRadioGroupEvents,
defineCustomElement: defineMyRadioGroup,
});
export const MyRadioGroup: StencilReactComponent<MyRadioGroupElement, MyRadioGroupEvents> =
/*@__PURE__*/ createComponent<MyRadioGroupElement, MyRadioGroupEvents>({
tagName: 'my-radio-group',
elementClass: MyRadioGroupElement,
react: React,
events: { onMyChange: 'myChange' } as MyRadioGroupEvents,
defineCustomElement: defineMyRadioGroup,
});

type MyRangeEvents = {
onMyChange: EventName<MyRangeCustomEvent<RangeChangeEventDetail>>;
onMyFocus: EventName<CustomEvent<void>>;
onMyBlur: EventName<CustomEvent<void>>;
};

export const MyRange = /*@__PURE__*/ createComponent<MyRangeElement, MyRangeEvents>({
export const MyRange: StencilReactComponent<MyRangeElement, MyRangeEvents> = /*@__PURE__*/ createComponent<
MyRangeElement,
MyRangeEvents
>({
tagName: 'my-range',
elementClass: MyRangeElement,
react: React,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,16 @@ export const defineContainer = <Props, VModelType = string | number | boolean>(
if (routerLink === EMPTY_PROP) return;

if (navManager !== undefined) {
/**
* This prevents the browser from
* performing a page reload when pressing
* an Ionic component with routerLink.
* The page reload interferes with routing
* and causes ion-back-button to disappear
* since the local history is wiped on reload.
*/
ev.preventDefault();

let navigationPayload: any = { event: ev };
for (const key in props) {
const value = props[key];
Expand Down Expand Up @@ -185,6 +195,17 @@ export const defineContainer = <Props, VModelType = string | number | boolean>(
}
}

// If router link is defined, add href to props
// in order to properly render an anchor tag inside
// of components that should become activatable and
// focusable with router link.
if (props[ROUTER_LINK_VALUE] !== EMPTY_PROP) {
propsToAdd = {
...propsToAdd,
href: props[ROUTER_LINK_VALUE],
};
}

/**
* vModelDirective is only needed on components that support v-model.
* As a result, we conditionally call withDirectives with v-model components.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
"sourceMap": true,
"jsx": "react",
"target": "esnext",
"types": ["jest"]
"types": ["jest"],
"skipLibCheck": true
},
"include": ["src/**/*.ts", "src/**/*.tsx"],
"exclude": ["./__tests__/**", "node_modules", "setupTests.ts"],
Expand Down
4 changes: 2 additions & 2 deletions packages/example-project/component-library/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"type": "git",
"url": "https://github.com/ionic-team/stencil-ds-output-targets.git"
},
"main": "dist/index.js",
"main": "dist/index.cjs.js",
"module": "dist/index.mjs",
"es2015": "dist/esm/index.mjs",
"es2017": "dist/esm/index.mjs",
Expand All @@ -31,7 +31,7 @@
},
"devDependencies": {
"@stencil/angular-output-target": "workspace:*",
"@stencil/core": "^4.16.0",
"@stencil/core": "^4.21.0",
"@stencil/react-output-target": "workspace:*",
"@stencil/vue-output-target": "workspace:*",
"@types/puppeteer": "2.0.1",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
:host {
display: block;
color: green;
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
| ---------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- |
| `accept` | `accept` | If the value of the type attribute is `"file"`, then this attribute will indicate the types of files that the server accepts, otherwise it will be ignored. The value must be a comma-separated list of unique content type specifiers. | `string` | `undefined` |
| `autocapitalize` | `autocapitalize` | Indicates whether and how the text value should be automatically capitalized as it is entered/edited by the user. | `string` | `'off'` |
| `autocomplete` | `autocomplete` | Indicates whether the value of the control can be automatically completed by the browser. | `"name" \| "on" \| "off" \| "honorific-prefix" \| "given-name" \| "additional-name" \| "family-name" \| "honorific-suffix" \| "nickname" \| "email" \| "username" \| "new-password" \| "current-password" \| "one-time-code" \| "organization-title" \| "organization" \| "street-address" \| "address-line1" \| "address-line2" \| "address-line3" \| "address-level4" \| "address-level3" \| "address-level2" \| "address-level1" \| "country" \| "country-name" \| "postal-code" \| "cc-name" \| "cc-given-name" \| "cc-additional-name" \| "cc-family-name" \| "cc-number" \| "cc-exp" \| "cc-exp-month" \| "cc-exp-year" \| "cc-csc" \| "cc-type" \| "transaction-currency" \| "transaction-amount" \| "language" \| "bday" \| "bday-day" \| "bday-month" \| "bday-year" \| "sex" \| "tel" \| "tel-country-code" \| "tel-national" \| "tel-area-code" \| "tel-local" \| "tel-extension" \| "impp" \| "url" \| "photo"` | `'off'` |
| `autocomplete` | `autocomplete` | Indicates whether the value of the control can be automatically completed by the browser. | `"off" \| "on" \| "name" \| "honorific-prefix" \| "given-name" \| "additional-name" \| "family-name" \| "honorific-suffix" \| "nickname" \| "email" \| "username" \| "new-password" \| "current-password" \| "one-time-code" \| "organization-title" \| "organization" \| "street-address" \| "address-line1" \| "address-line2" \| "address-line3" \| "address-level4" \| "address-level3" \| "address-level2" \| "address-level1" \| "country" \| "country-name" \| "postal-code" \| "cc-name" \| "cc-given-name" \| "cc-additional-name" \| "cc-family-name" \| "cc-number" \| "cc-exp" \| "cc-exp-month" \| "cc-exp-year" \| "cc-csc" \| "cc-type" \| "transaction-currency" \| "transaction-amount" \| "language" \| "bday" \| "bday-day" \| "bday-month" \| "bday-year" \| "sex" \| "tel" \| "tel-country-code" \| "tel-national" \| "tel-area-code" \| "tel-local" \| "tel-extension" \| "impp" \| "url" \| "photo"` | `'off'` |
| `autocorrect` | `autocorrect` | Whether auto correction should be enabled when the user is entering/editing the text value. | `"off" \| "on"` | `'off'` |
| `autofocus` | `autofocus` | This Boolean attribute lets you specify that a form control should have input focus when the page loads. | `boolean` | `false` |
| `clearInput` | `clear-input` | If `true`, a clear icon will appear in the input when there is a value. Clicking it clears the input. | `boolean` | `false` |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,19 +61,28 @@ export const config: Config = {
reactOutputTarget({
outDir: '../component-library-react/src',
}),
reactOutputTarget({
outDir: '../next-app/src/app',
hydrateModule: 'component-library/hydrate'
}),
vueOutputTarget({
componentCorePackage: 'component-library',
proxiesFile: '../component-library-vue/src/proxies.ts',
componentModels: vueComponentModels,
}),
{
type: 'dist-custom-elements',
externalRuntime: false,
dir: 'components'
},
{
type: 'dist',
esmLoaderPath: '../loader',
},
{
type: 'dist-hydrate-script',
dir: './hydrate',
},
{
type: 'docs-readme',
},
Expand Down
Loading