Code Monkey home page Code Monkey logo

stencil-ds-output-targets's Introduction

Project Package Version Documentation
React Output Target @stencil/react-output-target version README
Angular Output Target @stencil/angular-output-target version README
Vue Output Target @stencil/vue-output-target version README

Introduction

Integrating web components into existing framework applications can be difficult at times. More about this can be read at https://custom-elements-everywhere.com/. To accommodate the various issues, the Stencil team has created new output target plugins to make the process simpler.

The plugins add additional output targets for each framework binding that is included.

Here is an example project using the plugins for reference: https://github.com/ionic-team/stencil-ds-output-targets/blob/main/packages/example-project/component-library

Detailed information for each output target can be found in each package's README.

Maintenance Status

This project is currently maintained for the purposes of supporting the Ionic Framework. At this time, only new issues & pull requests that support the Ionic Framework will be prioritized.

Local development

Getting started

To set up this project and prepare the example project to be used in your own projects run the following commands.

npm install
npm run bootstrap
npm run build

This will generate all necessary builds in the example projects. You can then either publish the packages to npm or a private package manager, or use npm pack to start using the builds in a local project for testing purposes where you manually place the package in the project node_modules folder.

For example, if you have an Angular project, run npm pack in packages/example-project/component-library and packages/example-project/component-library-angular. Since the framework component libraries depend on the Stencil project, you will need to provide the component-library package in your project node_modules folder.

Node Versions

This project uses Volta to automatically manage what npm and node versions are used when developing. If you don't use Volta, don't worry about it... just check the root package.json for what version of node and npm is currently being used.

Deploying

There is a manual workflow task called "Production Release" within the GitHub Actions workflows directory. We currently do not release all packages that have been changed at once. You will need to deploy each package (vue, react, angular) individually.

You'll need to fill out a few bits of information when you submit the deploy workflow:

  1. Which package should be published (Currently vue, react, or angular).
  2. What version should be published.
  3. What npm tag it should be published under (next or latest)
  4. Any preid, like alpha or rc

stencil-ds-output-targets's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

stencil-ds-output-targets's Issues

@typescript-eslint/no-useless-constructor warning

createComponent.txt's ReactComponent class includes a constructor that does nothing:

constructor(props: StencilReactInternalProps<ElementType>) {
super(props);
}

In a create-react-app project, ESLint complains about this:

Compiled with warnings.

./src/react-component-lib/createComponent.tsx
Line 39:5: Useless constructor @typescript-eslint/no-useless-constructor

React Target doesn't pass window `defineCustomElement`

This is the output TS

/* eslint-disable */
/* tslint:disable */
/* auto-generated react proxies */
import { createReactComponent } from './react-component-lib';

import { JSX } from 'tinacms-ui';

import { defineCustomElements, applyPolyfills } from 'tinacms-ui/loader';

applyPolyfills().then(() => defineCustomElements());
export const MyComponent = /*@__PURE__*/createReactComponent<JSX.MyComponent, HTMLMyComponentElement>('my-component');

This code will not compile

It must be passed defineCustomElement(window)

Cannot find module `loader` or its corresponding type declarations.

@my-scope/[email protected] tsc /Users//Projects/component-library/packages/component-library-react
tsc -p .

src/components.ts:8:54 - error TS2307: Cannot find module '@my-scope/component-library/loader' or its corresponding type declarations.

8 import { defineCustomElements, applyPolyfills } from '@my-scope/component-library/loader';
~~~~~~~~~~~~~~~~~~~~~~~~

Found 1 error.

The above error was thrown when I tried to compile the react output of my component library which was generated using '@stencil/react-output-target'.

However, I was able to figure out the error. The import statement should be

8 import { defineCustomElements, applyPolyfills } from '@my-scope/component-library/dist/loader';

instead of

8 import { defineCustomElements, applyPolyfills } from '@my-scope/component-library/loader';

SSR warnings in NextJS

Carrying over from #37

The library that I published is here and is being used as follows:

import { ManifoldInit } from "@manifoldco/manifold-init-react/dist/components";

const Home = () => (
  <div className="container">
    <ManifoldInit env="stage" clientId="my-client-id" />

The app renders the component correctly but I've seen some warnings in NextJS.

SSR - Unhandled promise rejection

When I run my NextJS dev server, my terminal shows following error the first time I load the app:

(node:13529) UnhandledPromiseRejectionWarning: TypeError: head.querySelector is not a function
    at Object.bootstrapLazy (/home/sam/taco-cloud-react/node_modules/@manifoldco/manifold-init/dist/cjs/index-1ab6c73d.js:825:44)
    at /home/sam/taco-cloud-react/node_modules/@manifoldco/manifold-init/dist/cjs/loader.cjs.js:8:16
(node:13529) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:13529) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

I don't know if that's because NextJS is SSR and there's some code that shouldn't be running on the server side, but I tried rendering the component only when process.browser is defined and the error didn't go away, so it's hard to tell.

Again, the component renders fine on the page, but perhaps there are some places where SSR should be taken into account.

angular-output-target not working with Angular 8

I'm a bit new with Angular so please excuse any ignorance on my part. From all my digging and experimenting, I cannot get Stencil with angular-output-target working with Angular 8. Neither have I seen any documentation or notes on what versions it is compatible with - considering how fast Angular has major version updates, this is unfortunate.

This demo uses Angular 7.2 and I am able to get that working correctly.

However, when I create a fresh install of Stencil, follow the documentation here and on the demo template to set up angular-output-target and try to use it with a fresh installation of Angular 8, the app breaks.

The error thrown is NullInjectorError: No provider for ChangeDetectorRef

I'm unfortunately not familiar enough with Angular to know enough about ChangeDetectorRef or why it would be failing within a v8 ecosystem. I'd love to help update the plugin to work with Angular 8, so hopefully all of this makes sense and someone can shed some light on the issues!

Missing React component's data attributes

Thank you very much for this incredible work! Stencil is really awesome and allows us to unify our codebase for all projects!

But I noticed that generated React component can't have data attributes.
I don't know, maybe this is already known issue and there is some plan or roadmap to fix this.

Could you take a look on my PR, I believe it's able to fix this.
Thank you 🙏

stencil-ds-vue-template

Thanks for the new Vue Output Target! I look forward in using it.

But I haven't been able to get it working properly with my Stencil component library testing repo: https://github.com/elwinvaneede/elwins-test-web-components. Unlike the React & Angular output targets.

The docs say:

There is an example component library package available on Github so that you can get started.`

But I can't find the stencil-ds-vue-template repo (like https://github.com/ionic-team/stencil-ds-react-template & https://github.com/ionic-team/stencil-ds-angular-template), so I've had to guess the correct package.json setup.

I've also found the example-project in this repo, which seem like new example templates, but those package.json files seem to have unnecessary devDependencies like Rollup, and too many regular dependencies?

This is the one I currently use for my Vue output target: https://github.com/elwinvaneede/elwins-test-web-components-vue/blob/master/package.json.

But when using it in a Vue project created with the vue-cli, my components don't properly render. Any styling and functionality is missing. Only the text I add in a slot is visible in my browser. I can inspect the component in Chrome (where any props I've defined are not rendered). I don't get any console errors, and the Vue DevTools also show the components (with the props I've defined).

Do you have ideas how to fix this, and are there any plans on adding a stencil-ds-vue-template repo?

Thanks in advance.

what is the angularValueAccessorBindings on the new sencil angular plugin?

import { Config } from '@stencil/core';
import { angularOutputTarget, ValueAccessorConfig } from '@stencil/angular-output-target';

export const config: Config = { namespace: 'demo', outputTargets: [ angularOutputTarget({ componentCorePackage: 'component-library', directivesProxyFile: '../component-library-angular/src/directives/proxies.ts', valueAccessorConfigs: angularValueAccessorBindings, }), { type: 'dist', }, ], };

[React] 'slot' does not exist on component ts(2322)

If I have a Stencil component with named slots and another normal component:

...
class CompSlot {
  ...
  render() {
    return (<Host>
      <slot />
      <slot name='a'/>
    </Host>)
  }
}

...
class CompContent {
  ...
  render() {
    return (<Host>
      ...
    </Host>)
  }
}

When using the wrapped React component like this:

...
<CompSlot>
  Text
  <CompContent
    slot='a'
  />
</CompSlot>

Typescript throws the error slot does not exist on CompSlot.
If I silent the error with ts-ignore, the rendered result is correct and the CompContent was put inside the correct slot:

...
<comp-slot>
  Text
  <comp-content></comp-content>
</comp-slot>

React output target Typescript errors

  • "@stencil/react-output-target": "^0.0.7"
  • "@stencil/core": "^1.16.3"

The following errors can be seen and detected by typescript on react-component-lib/createComponent.tsx when building @Stencil library, therefore npm run build fail when trying to compile the react library:

CleanShot 2020-07-17 at 23 02 30@2x

I believe the fix is already in the master branch, is there some ETA about when a @stencil/[email protected] will come out?

Thank you!

Angular event types and docs

The outputs from the angular proxies should inherit the events from the stencil component class.

The current implementation adds the outputs as the properties of the angular class.

import { Components } from 'component-library'
export declare interface MyButton extends Components.MyButton {}
@ProxyCmp({ inputs: ["buttonType"] })
@Component({
  selector: "my-button",
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: "<ng-content></ng-content>",
  inputs: ["buttonType"],
})
export class MyButton {
  ionFocus!: EventEmitter<CustomEvent>;
  protected el: HTMLElement;
  constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) {
    c.detach();
    this.el = r.nativeElement;
    proxyOutputs(this, this.el, ["ionFocus"]);
  }
}

I believe they should be inherited from the stencil class like this to inherit types and docs in similar fashion to how inputs are added.

import { Components } from 'component-library'
++ import { Button as IButton } from 'component-library/dist/types/components/my-button/my-button'
++ export declare interface MyButton extends Required<Pick<IButton, 'ionFocus'>> {}
export declare interface MyButton extends Components.MyButton {}
@ProxyCmp({ inputs: ["buttonType"] })
@Component({
  selector: "my-button",
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: "<ng-content></ng-content>",
  inputs: ["buttonType"],
++  outputs: ["ionFocus"]
})
export class MyButton {
--  ionFocus!: EventEmitter<CustomEvent>;
  protected el: HTMLElement;
  constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) {
    c.detach();
    this.el = r.nativeElement;
    proxyOutputs(this, this.el, ["ionFocus"]);
  }
}

After upgrade to @stencil/react-output-target 0.0.7 render fails in react

Hello,

After upgrading @stencil/react-output-target from 0.0.6 to 0.0.7 my stencil components are failing silently and failing to render in React.

Inspecting createComponent.tsx it seems this function has changed quite abit. Please help me by providing some guidance on this issue, thanks much for your time.

Expected: After upgrade from 0.0.6 to 0.0.7 stencil components render in React.

Actual: After upgrade to 0.0.7, stencil components fail to render with no error messages.

Does this work for libraries that use stencil-state-tunnel?

Our component library uses stencil-state-tunnel. When I use the react-output-target to build a React component library, the first component that gets defined in components.ts looks like this:

export const ContextConsumer = createReactComponent<JSX.ContextConsumer, HTMLContextConsumerElement>('context-consumer');

TypeScript is highlighting two errors here:

Namespace 'LocalJSX' has no exported member 'ContextConsumer'

Cannot find name 'HTMLContextConsumerElement'

And indeed, when I use 'Go to Definition', it takes me to the dist/types/components.d.ts file, where the word Context does not appear at all.

bug(angular-output-target): incorrect path componentCorePackage name different than rootDir

When components rootDir (e.g. core) and componentCorePackage (e.g. @ionic/core) have different names the current interface import generates:

import { Checkbox as ICheckbox } from '../@ionic/core/dist/types/components/my-checkbox/my-checkbox';

Adjusting the relative import to the rootDir will accommodate all cases and generate the right path.

-  const typePath = path.relative(componentCorePackage, cmpMeta.sourceFilePath).replace('../src', path.join(componentCorePackage, distTypesDir)).replace('.tsx', '');
+  const typePath = path.parse(path.join(componentCorePackage, cmpMeta.sourceFilePath.replace(path.join(rootDir, 'src'), distTypesDir)));

-    ? `import { ${cmpMeta.componentClassName} as I${cmpMeta.componentClassName} } from '${typePath}';`
+    ? `import { ${cmpMeta.componentClassName} as I${cmpMeta.componentClassName} } from '${path.join(typePath.dir, typePath.name)}';`

Angular 10: Class is using Angular features but is not decorated

I am trying to use this library with Angular 10.
I get the following error when I try to build the Angular project:

src/directives/generated/value-accessor.ts:4:14 - error NG2007: Class is using Angular features but is not decorated. Please add an explicit Angular decorator.

4 export class ValueAccessor implements ControlValueAccessor {

This new behaviour seems to have been introduced by angular/angular#36921.

Manually appending @Directive() to ValueAccessor fixes the issue:

import {Directive, ElementRef, HostListener} from '@angular/core';
import { ControlValueAccessor } from '@angular/forms';

@Directive()
export class ValueAccessor implements ControlValueAccessor {
// ...

I wanted to create a pull request for that, but @Directive changed between Angular 9 and Angular 10.
In Angular 9, @Directive() requires a selector attribute, while in Angular 10, you can pass it without any option.

So maybe Stencil needs to be aware of the Angular version effectively used?

React: slot incompatibility

When a Stencil component uses a slot and is not using the shadow DOM, the React component should be able to dynamically update the children it passes the component (as slotted elements) and not have it completely overwrite the internals of the Stencil component.

For example:
A Stencil component implemented as such:

@Component({ tag: 'custom-button' })
export class CustomButton {
  render() {
    return (
      <button>
        <span>Pre-existing Content:</span>
        <slot />
      </button>
    );
  }
}

In React:

import React, { useState } from "react";
import { CustomButton } from "../../components";

export default function ButtonWrapper() {
  const [buttonText, setButtonText] = useState('button text')
  return (
    <>
      <CustomButton>{buttonText}</CustomButton>
      <input value={buttonText} onChange={e => setButtonText(e.target.value)}></input>
    </>
  );
}

On initial render, the custom button's DOM looks like:

<custom-button class="hydrated">
  <button>
    <span>Pre-existing Content:</span>
    <span class>button text</span>
  </button>
</custom-button>

When we update the value and thereby the slotted content that gets rendered inside the <slot /> in our custom button, the DOM looks like this:

<custom-button class="hydrated">updated text</custom-button>

thereby wiping out the internal structure of our custom element.

I am aware that using shadow DOM is a possible remedy to this problem, however there are actual bugs in Google Chrome with shadow DOM that prevent us from completely adopting shadow DOM across the board.

[Bug] [Angular] proxies.ts: Incorrect relative import path

Versions:

  • @stencil/core 1.15.0
  • @stencil/angular-output-target 0.0.3
  • tslib 1.13.0
  • @angular/core 9.1.11
  • @angular/common 9.1.11
  • typescript 3.8.3

Our stencil.config.ts looks like this:

import { Config } from '@stencil/core';
import { angularOutputTarget, ValueAccessorConfig } from '@stencil/angular-output-target';

export const config: Config = {
  namespace: 'schwarz-core-ui',
  globalScript: 'src/global/global.ts',
  globalStyle: './src/assets/index.global.less',
  outputTargets: [
  ...
    angularOutputTarget({
      componentCorePackage: '@my/lib',
      directivesProxyFile: '../my-lib-angular-bindings/src/directives/proxies.ts',
      directivesArrayFile: '../my-lib-angular-bindings/src/directives/array.ts',
      directivesUtilsFile: '../my-lib-angular-bindings/src/directives/utils.ts',
      valueAccessorConfigs,
    }),
  ],
};

The proxy.ts import path tries to import the component types from the incorrect relative path ../my-lib-repo/dist/types/components/.
Instead it should just reference the package directly (via package name @my/lib) like in the first line of this proxy.ts snippet:

// my-lib-angular-bindings/src/directives/proxies.ts
...
import { Components } from '@my/lib' // <= Uses library here correctly
import { MyAccordion as IMyAccordion } from '../my-lib-repo/dist/types/components/my-accordion/my-accordion'; // <= refernces original repo incorrectly
export declare interface MyAccordion extends Components.MyAccordion {}
@ProxyCmp({inputs: ['accordionStyle', 'disabled', 'open', 'toggleClickArea']})
@Component({ selector: 'my-accordion', changeDetection: ChangeDetectionStrategy.OnPush, template: '<ng-content></ng-content>', inputs: ['accordionStyle', 'disabled', 'open', 'toggleClickArea'], outputs: ['myaccordiontoggle'] })
...

bug(angular-output-target): events fire twice

Since the events are added to the outputs array - there's no need to create an observable listener anymore to bubble the events. Instead - to keep the outputs array and the types, fromEvent can be replaced with an empty EventEmitter in the angular proxy utils.

export const proxyOutputs = (instance: any, el: any, events: string[]) => {
--  events.forEach((eventName) => (instance[eventName] = fromEvent(el, eventName)));
++  events.forEach((eventName) => (instance[eventName] = new EventEmitter()));
};

React: StrictMode deprecations and SSR warnings

Hello and thank you for this great plugin. It shows lots of promise for making web component libraries easier to consume from React. That said, I have observed a couple warnings I've encountered while trying to use the React components within React applications.

The library that I published is here and is being used as follows:

import { ManifoldInit } from "@manifoldco/manifold-init-react/dist/components";

const Home = () => (
  <div className="container">
    <ManifoldInit env="stage" clientId="my-client-id" />

The app renders the component correctly but I've seen some warnings both in CRA and NextJS.

CRA - StrictMode warning

When I use create-react-app I get the following warning in my browser console:

Warning: findDOMNode is deprecated in StrictMode. findDOMNode was passed an instance of ManifoldInit which is inside StrictMode. Instead, add a ref directly to the element you want to reference. Learn more about using refs safely here: https://fb.me/react-strict-mode-find-node
    in manifold-init (created by ManifoldInit)
    in ManifoldInit (created by ForwardRef(ManifoldInit))
    in ForwardRef(ManifoldInit) (at App.js:9)
    in div (at App.js:8)
    in App (at src/index.js:9)
    in StrictMode (at src/index.js:8)

I'd probably trace this to the createReactComponent which contains this in the cjs build:

        componentDidUpdate(prevProps) {
            const node = ReactDom.findDOMNode(this);
            attachEventProps(node, this.props, prevProps);
        }

The component renders as it should for now but since findDOMNode is deprecated I expect that this will break in the future. Can this be updated to support StrictMode properly?

SSR - Unhandled promise rejection

When I run my NextJS dev server, my terminal shows following error the first time I load the app:

(node:13529) UnhandledPromiseRejectionWarning: TypeError: head.querySelector is not a function
    at Object.bootstrapLazy (/home/sam/taco-cloud-react/node_modules/@manifoldco/manifold-init/dist/cjs/index-1ab6c73d.js:825:44)
    at /home/sam/taco-cloud-react/node_modules/@manifoldco/manifold-init/dist/cjs/loader.cjs.js:8:16
(node:13529) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:13529) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

I don't know if that's because NextJS is SSR and there's some code that shouldn't be running on the server side, but I tried rendering the component only when process.browser is defined and the error didn't go away, so it's hard to tell.

Again, the component renders fine on the page, but perhaps there are some places where SSR should be taken into account.

[Angular] proxies.ts: import path with "/dist/"

  • @stencil/angular-output-target": "^0.0.3"
  • @stencil/core": "^1.16.3"

When creating the component definition in the proxies.ts for components with events, the compiler generates an import that looks like this as mentioned in #86 and #95
import { Input as IInput } from '../component-library/dist/types/components/my-input/my-input';

the issue within the relative import seems to be fixed in the code that is currently in the master branch but another concern is the /dist/ in the generated import.

Since we don't intend to maintain the two projects as siblings. I'd like a way to generate this import path without the /dist/, like this
import { Input as IInput } from 'component-library/types/components/my-input/my-input';

React - undefined event handlers should be ignored

In normal React components, the following is a no-op:

<SomeComponent onSomeEvent={undefined} />

This is useful in cases where props are optional, or handlers are conditional for some other reason. E.g.

const TestInput = ({ name, onBlur, onChange }) => (
  <input name={name} onBlur={onBlur} onChange={onChange} />
)

But will fail when used similarly with a wrapped stencil component if onBlur is not supplied:

const TestInput = ({ name, onBlur, onChange }) => (
  <MyStencilInput name={name} onBlur={onBlur} onChange={onChange} />
)
// attachEventProps.js?9a31:67 Uncaught TypeError: Cannot read property 'call' of undefined
//    at HTMLElement.handler (attachEventProps.js?9a31:67)

The addEventListener call below should be wrapped in a newEventHandler != null check (or possibly even a typeof newEventHandler === 'function')
https://github.com/ionic-team/stencil-ds-plugins/blob/1ed6161741d6210ebbe4def607a4d3532e804b8a/packages/react-output-target/react-component-lib/utils/attachEventProps.ts#L73

[React]: TS2345 - Type 'null' is not assignable to type 'HTMLElement'.

Context

I created a React set of components using https://github.com/ionic-team/stencil-ds-react-template and @stencil/react-output-target and the stencil project I'm using is largely based on the default config.

We use Renovate in our project which bumps the versions of packages automatically and our CI pipeline fails at the build stage due to the TS issue

Description of issue

When updating @stencil/react-output-target from 0.0.4 -> 0.0.6

Build then causes an error in the createComponent script:

src/react-component-lib/createComponent.tsx:32:24 - error TS2345: Argument of type 'HTMLElement | null' is not assignable to parameter of type 'HTMLElement'.
  Type 'null' is not assignable to type 'HTMLElement'.

32       attachEventProps(node, this.props, prevProps);

It looks like one of the following is true:

  • The version of react / types I'm using is different (i.e. in the version used node is just HTMLElement)
  • The TSConfig you use does not catch the potentially null element
  • The code is missing a level of 'compliance test' (i.e. check that you can actually 'build' with the relevant code)
  • I configured something wrong and screwed it up in my config 😅

Hoping it's a simple fix - It currently means we can't update.

Possibly related dependencies

In the 'react' package (based on the template)

{
  "devDependencies": {
    "@types/react": "16.9.35",
    "@types/react-dom": "16.9.8",
    "react": "16.13.1",
    "react-dom": "16.13.1",
    "typescript": "3.8.3"
  }
}

In the 'core' package

{
  "devDependencies": {
    "@babel/core": "7.9.6",
    "@babel/preset-env": "7.9.6",
    "@babel/preset-typescript": "7.9.0",
    "@stencil/angular-output-target": "0.0.2",
    "@stencil/core": "1.12.7",
    "@stencil/eslint-plugin": "0.3.1",
    "@stencil/postcss": "1.0.1",
    "@stencil/react-output-target": "0.0.6",
    "@storybook/addon-info": "5.3.18",
    "@storybook/addon-knobs": "5.3.18",
    "@storybook/addon-notes": "5.3.18",
    "@storybook/addon-viewport": "5.3.18",
    "@storybook/html": "5.3.18",
    "@types/jest": "25.2.1",
    "@types/puppeteer": "2.0.1",
    "@types/storybook__addon-knobs": "5.2.1",
    "@types/storybook__html": "5.2.1",
    "@typescript-eslint/eslint-plugin": "2.31.0",
    "@typescript-eslint/parser": "2.31.0",
    "awesome-typescript-loader": "5.2.1",
    "babel-loader": "8.1.0",
    "babel-plugin-dynamic-import-node": "2.3.3",
    "case": "1.6.3",
    "cssnano": "4.1.10",
    "eslint": "6.8.0",
    "eslint-config-airbnb-base": "14.1.0",
    "eslint-config-airbnb-typescript": "7.2.1",
    "eslint-plugin-import": "2.20.2",
    "eslint-plugin-jsx-a11y": "6.2.3",
    "eslint-plugin-react": "7.19.0",
    "eslint-plugin-react-hooks": "4.0.0",
    "glob": "7.1.6",
    "jest": "24.9.0",
    "jest-cli": "24.9.0",
    "npm-run-all": "4.1.5",
    "postcss-calc": "7.0.2",
    "postcss-custom-properties": "9.1.1",
    "postcss-import": "12.0.1",
    "postcss-preset-env": "6.7.0",
    "puppeteer": "3.0.4",
    "rimraf": "3.0.2",
    "storybook": "5.3.18",
    "typescript": "3.8.3",
    "webpack": "4.43.0",
    "workbox-build": "5.1.3"
  }
}

React Target doesn't pass window `defineCustomElement` which is required in loader file

Output of ts

/* eslint-disable */
/* tslint:disable */
/* auto-generated react proxies */
import { createReactComponent } from './react-component-lib';

import { JSX } from 'stencil-components';

import { defineCustomElements, applyPolyfills } from 'stencil-components';

applyPolyfills().then(() => defineCustomElements());

file: loader/index.d.ts

export declare function defineCustomElements(win: Window, opts?: CustomElementsDefineOptions): Promise<void>;

React Output Target deletes output if it already exists

I have configured my react output target to live in ./dist/react as follows:

reactOutputTarget({
  proxiesFile: './dist/react/index.ts',
}),

When I run stencil build once, the proxies file and react-component-lib dir get created in ./dist/react. However, if I run stencil build again the ./dist/react dir is being removed entirely.

So in order to rebuild react components I need to run stencil build twice. Desired behavior would be to have the output target created with latest changes every time I run stencil build

Angular Ivy Break

Install Angular ^9 and import Angular-wrapped web-components created via the stencil.config.ts output target.

You'll see this error when importing the angular-wrapped component library.

Update 2
It appears that the problem is related to the Ivy compiler and symlinks. Using preserveSymlink: true in the angular.json and angularCompiler options did nothing to help. Only creating a release to npm and installing from remote resolved the Ivy build issues for me.

I'd love if someone could shed some light on this.

Update
I did some more work following the ionic/ionic repo as an example, this is what I'm now stuck on:

ERROR Error: inject() must be called from an injection context
at injectInjectorOnly (core.js:899)
at ɵɵinject (core.js:915)
at Module.ɵɵdirectiveInject (core.js:20756)
at NodeInjectorFactory.XdsButton_Factory [as factory] (system-angular.js:97)
at getNodeInjectable (core.js:5598)
at instantiateAllDirectives (core.js:12645)
at createDirectivesInstances (core.js:11881)
at Module.ɵɵelementStart (core.js:20943)
at AppComponent_Template (app.component.html:6)
at executeTemplate (core.js:11841)

I'm using ng-packager 9, Angular 9, and I'm no longer using the ds-plugins - I'm just using the angular compiler option shipped in stencil 1.8.7. My tsconfig for angular is below.

{
  "angularCompilerOptions": {
    "annotateForClosureCompiler": true,
    "strictMetadataEmit": true,
    "flatModuleOutFile": "core.js",
    "flatModuleId": "@system/angular",
    "skipTemplateCodegen": true,
    "fullTemplateTypeCheck": false,
    "enableResourceInlining": true,
    "enableIvy": false
  },
  "compilerOptions": {
    "alwaysStrict": true,
    "strict": true,
    "allowSyntheticDefaultImports": true,
    "allowUnreachableCode": false,
    "declaration": true,
    "declarationDir": "dist",
    "experimentalDecorators": true,
    "forceConsistentCasingInFileNames": true,
    "lib": ["dom", "es2017"],
    "module": "es2015",
    "moduleResolution": "node",
    "noImplicitAny": true,
    "noImplicitReturns": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "outDir": "build/es2015",
    "pretty": true,
    "removeComments": false,
    "importHelpers": true,
    "rootDir": "src",
    "strictPropertyInitialization": false,
    "target": "es2015",
    "baseUrl": ".",
    "paths": {
      "@system/core": ["../core"]
    }
  },
  "exclude": ["node_modules", "src/schematics"],
  "files": ["src/index.ts"]
}

ERROR in getInternalNameOfClass() called on a non-ES5 class: expected XdsBadge to have an inner class declaration

With aot disabled, this warning is thrown in the terminal:

WARNING in Invalid constructor parameter decorator in /Users/jsmith582/dev/components/packages/angular/dist/fesm2015.js:
() => [
{ type: ChangeDetectorRef },
{ type: ElementRef },
{ type: NgZone }
]

react-output-target is skipped with --dev

I couldn't find a clear answer why, but through trial-and-error I learned that bindings are only generated for production, not when --dev is passed:

https://github.com/ionic-team/stencil-ds-plugins-demo/blob/04f0108046c02ca494dd6551b1dd822d16b87b8d/packages/component-library/package.json#L15-L16

I can remove --dev easy enough, but I want to understand the implications of this (cannot find documentation clearly stating what it does).

My goal is to generate bindings during development so I can leverage Storybook for showing both my Stencil components and stories for Angular/React/Vue.

Can’t customize the import path in the generated proxiesFile

First of all, thank you so much for open sourcing this. This is really useful addition to our team’s toolchain.

One issue we faced while implementing this is that it doesn’t seem to be possible to customize the import path in the generated proxiesFile. So in our case, the generated import line in proxiesFile looks like this:

import { defineCustomElements, applyPolyfills } from "@duetds/components/loader"

But it should actually be:

import { defineCustomElements, applyPolyfills } from "@duetds/components/lib/loader"

Is there a way to customize this somehow or specify the import path in config?

ref prop of React Components is not working

Hello folks

I have this code from a React project:

<IonPhaser ref={(ref) => console.log(ref)} game={game} initialize={initialize} />

But the console.log never runs, therefore useRef of React is not working:

import React, { useRef } from 'react'

export default function App () {
  const gameRef = useRef<HTMLIonPhaserElement>(null)
  const debug = () => {
    console.log('Reference', gameRef.current) // Always is null
  }

  return (
    <>
      <IonPhaser ref={gameRef} game={game} initialize={initialize} />
      <button onClick={debug}>Debug</button>
    </>
  )
}

This is the project: https://github.com/proyecto26/ion-phaser

Thanks in advance!
Regards

[Bug] [Angular] Value Accessors files are invalid typescript for multiple events for a single type

Versions:

  • @stencil/core 1.15.0
  • @stencil/angular-output-target 0.0.3
  • tslib 1.13.0
  • @angular/core 9.1.11
  • @angular/common 9.1.11
  • typescript 3.8.3

I provide an ValueAccessorConfig with multiple different elementSelectors and events for a single type: E.g.:

const valueAccessorConfig = [
{
    elementSelectors: 'my-input',
    event: 'myinputchange',
    targetAttr: 'value',
    type: 'text',
},
{
    elementSelectors: 'my-search',
    event: 'mysearchtrigger',
    targetAttr: 'value',
    type: 'text',
}
];

The build produces invalid typescript by missing "," at the end of the lines:

// text-value-accessor.ts
...
@Directive({
  /* tslint:disable-next-line:directive-selector */
  selector: 'scu-input, scu-search, scu-text-area',
  host: {
    '(scuinputchange)': 'handleChangeEvent($event.target.value)' 
    '(scusearchtrigger)': 'handleChangeEvent($event.target.value)' //  <=  ',' expected. ts(1005)
    '(scutextareainput)': 'handleChangeEvent($event.target.value)' //  <=  ',' expected. ts(1005)
  },
...

Angular Output Target "Cannot Find Module" On Compile

"@stencil/angular-output-target": "^0.0.3"
"@stencil/core": "^1.16.3"

Upgrading angular-output-target from 0.0.2 to 0.0.3, the proxies.ts file now adds an import statement for each component, e.g.:
import { TabsLabelComponent as ITabsLabelComponent } from '../@meridian/web/dist/types/lib/components/tabs/mds-tabs-label';

The pathing is not right for my project however, I don't want the "../" at the start of the path. Expected output would be:

import { TabsLabelComponent as ITabsLabelComponent } from '@meridian/web/dist/types/lib/components/tabs/mds-tabs-label';

On compile, I get the following error due to the pathing:

libs/angular/src/lib/directives/proxies.ts:568:59 - error TS2307: Cannot find module '../@meridian/web/dist/types/lib/components/tabs/mds-tabs-label'.

568 import { TabsLabelComponent as ITabsLabelComponent } from '../@meridian/web/dist/types/lib/components/tabs/mds-tabs-label';

Here is my stencil.config.ts blurb for the Angular output target:

angularOutputTarget({
      componentCorePackage: '@meridian/web',
      directivesProxyFile: resolve(
        __dirname,
        '../angular/src/lib/directives/proxies.ts'
      ),
      directivesUtilsFile: resolve(
        __dirname,
        '../angular/src/lib/directives/proxies-utils.ts'
      ),
      directivesArrayFile: resolve(
        __dirname,
        '../angular/src/lib/directives/proxies-list.txt'
      ),
      excludeComponents: [],
      valueAccessorConfigs: [],
    }),

Is there a way to prevent that relative pathing prefix to be added to the import?

[Bug] [Angular] Separated accessor classes for target attributes that are not named "value"

Versions:

  • @stencil/core 1.15.0
  • @stencil/angular-output-target 0.0.3
  • tslib 1.13.0
  • @angular/core 9.1.11
  • @angular/common 9.1.11
  • typescript 3.8.3

Our valueAccessorConfigs for the angularOutputTarget looks like this:

[
{
    elementSelectors: 'scu-checkbox',
    event: 'scucheckboxchange',
    targetAttr: 'value',
    type: 'boolean',
},
{
    elementSelectors: 'scu-switch',
    event: 'scuswitchchange',
    targetAttr: 'checked',
    type: 'boolean',
}
]

Which produces the following boolean-value-accessor.ts

// boolean-value-accessor.ts
import { Directive, ElementRef } from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';

import { ValueAccessor } from './value-accessor';

@Directive({
  /* tslint:disable-next-line:directive-selector */
  selector: 'scu-checkbox, scu-switch',
  host: {
    '(scucheckboxchange)': 'handleChangeEvent($event.target.value)'
    '(scuswitchchange)': 'handleChangeEvent($event.target.checked)'
  },
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: BooleanValueAccessor,
      multi: true
    }
  ]
})
export class BooleanValueAccessor extends ValueAccessor {
  constructor(el: ElementRef) {
    super(el);
  }
  writeValue(value: any) {
    this.el.nativeElement.checked = this.lastValue = value == null ? false : value; // <= this will only work for scu-switch web component
  }
}

The writeValue method of the ValueAccessor is only being overwritten for targetAttr of the scu-switch web-component and won't work for scu-checkbox web-component with the targetAttr "value".
In this case the selectors should probably not be merged into one ValueAccessor Directive, but be two separate directives.

[Publish] New @react-output-target version in NPM with important updates.

I'm having a problem with @react-output-target - version 0.0.6 (latest), when I'm trying to build the package the tcs I receive this throble:

src/react-component-lib/createOverlayComponent.tsx(15,17): error TS2742: 
The inferred type of 'createOverlayComponent' 
cannot be named without a reference to 'react-dom/node_modules/@types/react'. 
This is likely not portable. A type annotation is necessary.

I saw that the commit 9d385ee fixed this problem and it was merged with the master branch, but it is not available in version 0.0.6 in NPM.

so, when will you guys publish a new version with these important updates?

defineCustomElements no longer called by default in react-output-target

In 0.0.6 the output included defineCustomElements by default. As of 0.0.7 this is no longer the case.

I notice new config options were introduced:

  • includeDefineCustomElements
  • includePolyfills

Looking at the code, it seems these should default to true but for whatever reason, this is not happening.

My suspicion is that whilst the logic in normalizeOutputTarget is correct, the result of that function is not used anywhere. If you look at the generator method, it is referencing to the closed over outputTarget rather than the normalised result.

Of course I can workaround this by explicitly setting the options, but it took me some time to work out why things suddenly broke, and fixing this may save someone else the effort :)

Input bindings with Angular output target in prod mode (--prod)

I am having an issue where a proxied component is not accepting input bindings. I am required to use attribute bindings to pass data:

// This does NOT WORK and the [value] gets an empty string (nothing)
<my-textarea *ngFor="let value of values" [value]="value"></my-textarea>

// This DOES work and the [value] gets the expected data
<my-textarea *ngFor="let value of values" [attr.value]="value"></my-textarea>

I noticed it works as expected when using an ionic component:

// Works
<ion-input *ngFor="let color of colors" [value]="color"></ion-input>

I cannot see the difference between what Ionic does and what this plugin does. (or even what the built-in Stencil angular output target does. Does anyone have some insight?

Thanks!

react-component-lib depends on @stencil/core

Having just upgraded to 0.0.7 of the React output target, I got this error in my consuming React project:

/path/to/react-app/src/react-component-lib/createComponent.tsx
TypeScript error in /path/to/react-app/src/react-component-lib/createComponent.tsx(10,36):
Cannot find module '@stencil/core/internal/stencil-public-runtime' or its corresponding type declarations. TS2307

It looks like a runtime dependency on @stencil/core has been introduced into the build output of react-output-target. That would mean that every React app that consumes React proxies would need to add Stencil to its package.json, which I do not believe is how react-output-target is intended to work (and wasn't the case for 0.0.6).

The dependency was introduced by 1b0a49c#diff-0c5775a0b0c1a17c5b8e386f105c1683R10.

Using component-library-angular in an Angular 8 app gives: "error TS1086: An accessor cannot be declared in an ambient context"

I will document my steps so to best describe the use case.

  1. After cloning the repo from master I run the following commands:
npm install
npm run bootstrap
npm run build
  1. Next I run npm pack on component-library and component-library-angular so I can use these packages in an Angular 8 application I locally created.

  2. Next I import the ComponentLibraryModule in app.module.ts, add it to imports and run ng serve.

import { ComponentLibraryModule } from 'component-library-angular';

@NgModule({
  imports: [
    ComponentLibraryModule
  ]
})
  1. This gives me the following error:
ERROR in node_modules/component-library/dist/types/components/my-range/my-range.d.ts:113:17 - error TS1086: An accessor cannot be declared in an ambient context.

113     private get valA();
                    ~~~~
node_modules/component-library/dist/types/components/my-range/my-range.d.ts:114:17 - error TS1086: An accessor cannot be declared in an ambient context.

114     private get valB();
                    ~~~~
node_modules/component-library/dist/types/components/my-range/my-range.d.ts:115:17 - error TS1086: An accessor cannot be declared in an ambient context.

115     private get ratioLower();
                    ~~~~~~~~~~
node_modules/component-library/dist/types/components/my-range/my-range.d.ts:116:17 - error TS1086: An accessor cannot be declared in an ambient context.

116     private get ratioUpper();

StaticInjectorError in angular 8 project

Hello. I originally posted this issue in the demo project repo, but have not got any response in a week, so thought I would also post it here, since I believe it actually an issue with the plugin.

see ionic-team/stencil-ds-plugins-demo#14

Steps to Repro:

  1. Clone repo: https://github.com/ionic-team/stencil-ds-plugins-demo
  2. npm install
  3. lerna bootstrap
  4. build component-library
  5. build component-library-angular
  6. 'npm start' app-angular
  7. Open http://localhost:4200 in Chrome (80)

See following error in console (twice)

AppComponent.html:3 ERROR NullInjectorError: StaticInjectorError(AppModule)[DemoComponent -> ChangeDetectorRef]:
StaticInjectorError(Platform: core)[DemoComponent -> ChangeDetectorRef]:
NullInjectorError: No provider for ChangeDetectorRef!
at NullInjector.push../node_modules/@angular/core/fesm5/core.js.NullInjector.get (http://localhost:4200/vendor.js:89853:25)
at resolveToken (http://localhost:4200/vendor.js:101046:24)
at tryResolveToken (http://localhost:4200/vendor.js:100990:16)
at StaticInjector.push../node_modules/@angular/core/fesm5/core.js.StaticInjector.get (http://localhost:4200/vendor.js:100892:20)
at resolveToken (http://localhost:4200/vendor.js:101046:24)
at tryResolveToken (http://localhost:4200/vendor.js:100990:16)
at StaticInjector.push../node_modules/@angular/core/fesm5/core.js.StaticInjector.get (http://localhost:4200/vendor.js:100892:20)
at resolveNgModuleDep (http://localhost:4200/vendor.js:109362:29)
at NgModuleRef_.push../node_modules/@angular/core/fesm5/core.js.NgModuleRef_.get (http://localhost:4200/vendor.js:110033:16)
at resolveDep (http://localhost:4200/vendor.js:110404:45)

Script compatibility on non *nix systems

I have noticed several things when running the bootstrap command.

  • Jest tests fail where the following path is used: Windows doesn't seem to handle the ../../node_modules/.bin/jest path. This can be fixed by added Jest as a dev dependency to the affected projects and changing ../../node_modules/.bin/jest to just jest --passWithNoTests. Needs to be changed per Lerna package. I did some investigation regarding common dev dependencies with Lerna and found the following (https://github.com/lerna/lerna#common-devdependencies): "Note that devDependencies providing "binary" executables that are used by npm scripts still need to be installed directly in each package where they're used."
  • Rimraf is not used in all packages. Since Windows doesn't know rm -rf this breaks the build. Needs to be installed per Lerna package. Is the case in component-library-vue and component-library-react.
  • The generated component import paths for the Angular output are not right. Output is something like this component-library\C:\Users\jan.dewilde\projects\stencil-ds-output-targets\packages\example-project\component-library\src\components\my-button\my-button. I fixed this by changing the way the import path is assembled so this generates component-library/dist/types/components/my-button/my-button.

The changed code is from:

const typePath = path.parse(path.join(componentCorePackage, cmpMeta.sourceFilePath.replace(path.join(rootDir, 'src'), distTypesDir)));

To:

  const typePath = path.parse(path.join(componentCorePackage, path.join(cmpMeta.sourceFilePath, '').replace(path.join(rootDir, 'src'), distTypesDir)))
  const importPath = path.join(typePath.dir, typePath.name).replace(/\\/g, "/");

I'm willing to open a Pull Request with changes, but it would be great if someone on a *nix system would like to validated the path fix, since I don't have a Mac anymore (and no WSL (yet)).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.