From 6d1e236f741ea05ff70ac12974e1d8bc28abb47d Mon Sep 17 00:00:00 2001 From: Ryan Waskiewicz Date: Fri, 7 Oct 2022 09:52:28 -0400 Subject: [PATCH] run: npm init stencil component my-lib --- my-lib/.editorconfig | 15 ++++ my-lib/.gitignore | 26 +++++++ my-lib/.prettierrc.json | 13 ++++ my-lib/LICENSE | 21 ++++++ my-lib/package.json | 38 ++++++++++ my-lib/readme.md | 75 +++++++++++++++++++ my-lib/src/components.d.ts | 61 +++++++++++++++ .../components/my-component/my-component.css | 3 + .../my-component/my-component.e2e.ts | 32 ++++++++ .../my-component/my-component.spec.ts | 36 +++++++++ .../components/my-component/my-component.tsx | 32 ++++++++ my-lib/src/components/my-component/readme.md | 19 +++++ my-lib/src/index.html | 14 ++++ my-lib/src/index.ts | 1 + my-lib/src/utils/utils.spec.ts | 19 +++++ my-lib/src/utils/utils.ts | 3 + my-lib/stencil.config.ts | 21 ++++++ my-lib/tsconfig.json | 25 +++++++ 18 files changed, 454 insertions(+) create mode 100644 my-lib/.editorconfig create mode 100644 my-lib/.gitignore create mode 100644 my-lib/.prettierrc.json create mode 100644 my-lib/LICENSE create mode 100644 my-lib/package.json create mode 100644 my-lib/readme.md create mode 100644 my-lib/src/components.d.ts create mode 100644 my-lib/src/components/my-component/my-component.css create mode 100644 my-lib/src/components/my-component/my-component.e2e.ts create mode 100644 my-lib/src/components/my-component/my-component.spec.ts create mode 100644 my-lib/src/components/my-component/my-component.tsx create mode 100644 my-lib/src/components/my-component/readme.md create mode 100644 my-lib/src/index.html create mode 100644 my-lib/src/index.ts create mode 100644 my-lib/src/utils/utils.spec.ts create mode 100644 my-lib/src/utils/utils.ts create mode 100644 my-lib/stencil.config.ts create mode 100644 my-lib/tsconfig.json diff --git a/my-lib/.editorconfig b/my-lib/.editorconfig new file mode 100644 index 0000000..f1cc3ad --- /dev/null +++ b/my-lib/.editorconfig @@ -0,0 +1,15 @@ +# http://editorconfig.org + +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +insert_final_newline = false +trim_trailing_whitespace = false diff --git a/my-lib/.gitignore b/my-lib/.gitignore new file mode 100644 index 0000000..c3ea58a --- /dev/null +++ b/my-lib/.gitignore @@ -0,0 +1,26 @@ +dist/ +www/ +loader/ + +*~ +*.sw[mnpcod] +*.log +*.lock +*.tmp +*.tmp.* +log.txt +*.sublime-project +*.sublime-workspace + +.stencil/ +.idea/ +.vscode/ +.sass-cache/ +.versions/ +node_modules/ +$RECYCLE.BIN/ + +.DS_Store +Thumbs.db +UserInterfaceState.xcuserstate +.env diff --git a/my-lib/.prettierrc.json b/my-lib/.prettierrc.json new file mode 100644 index 0000000..7ca3a28 --- /dev/null +++ b/my-lib/.prettierrc.json @@ -0,0 +1,13 @@ +{ + "arrowParens": "avoid", + "bracketSpacing": true, + "jsxBracketSameLine": false, + "jsxSingleQuote": false, + "quoteProps": "consistent", + "printWidth": 180, + "semi": true, + "singleQuote": true, + "tabWidth": 2, + "trailingComma": "all", + "useTabs": false +} diff --git a/my-lib/LICENSE b/my-lib/LICENSE new file mode 100644 index 0000000..b442934 --- /dev/null +++ b/my-lib/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/my-lib/package.json b/my-lib/package.json new file mode 100644 index 0000000..614fddc --- /dev/null +++ b/my-lib/package.json @@ -0,0 +1,38 @@ +{ + "name": "my-lib", + "version": "0.0.1", + "description": "Stencil Component Starter", + "main": "dist/index.cjs.js", + "module": "dist/index.js", + "es2015": "dist/esm/index.mjs", + "es2017": "dist/esm/index.mjs", + "types": "dist/types/index.d.ts", + "collection": "dist/collection/collection-manifest.json", + "collection:main": "dist/collection/index.js", + "unpkg": "dist/my-lib/my-lib.esm.js", + "repository": { + "type": "git", + "url": "/~https://github.com/ionic-team/stencil-component-starter.git" + }, + "files": [ + "dist/", + "loader/" + ], + "scripts": { + "build": "stencil build --docs", + "start": "stencil build --dev --watch --serve", + "test": "stencil test --spec --e2e", + "test.watch": "stencil test --spec --e2e --watchAll", + "generate": "stencil generate" + }, + "dependencies": { + "@stencil/core": "^2.13.0" + }, + "devDependencies": { + "@types/jest": "^27.0.3", + "jest": "^27.4.5", + "jest-cli": "^27.4.5", + "puppeteer": "^10.0.0" + }, + "license": "MIT" +} diff --git a/my-lib/readme.md b/my-lib/readme.md new file mode 100644 index 0000000..3db484f --- /dev/null +++ b/my-lib/readme.md @@ -0,0 +1,75 @@ +![Built With Stencil](https://img.shields.io/badge/-Built%20With%20Stencil-16161d.svg?logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE5LjIuMSwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHZpZXdCb3g9IjAgMCA1MTIgNTEyIiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCA1MTIgNTEyOyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI%2BCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI%2BCgkuc3Qwe2ZpbGw6I0ZGRkZGRjt9Cjwvc3R5bGU%2BCjxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik00MjQuNywzNzMuOWMwLDM3LjYtNTUuMSw2OC42LTkyLjcsNjguNkgxODAuNGMtMzcuOSwwLTkyLjctMzAuNy05Mi43LTY4LjZ2LTMuNmgzMzYuOVYzNzMuOXoiLz4KPHBhdGggY2xhc3M9InN0MCIgZD0iTTQyNC43LDI5Mi4xSDE4MC40Yy0zNy42LDAtOTIuNy0zMS05Mi43LTY4LjZ2LTMuNkgzMzJjMzcuNiwwLDkyLjcsMzEsOTIuNyw2OC42VjI5Mi4xeiIvPgo8cGF0aCBjbGFzcz0ic3QwIiBkPSJNNDI0LjcsMTQxLjdIODcuN3YtMy42YzAtMzcuNiw1NC44LTY4LjYsOTIuNy02OC42SDMzMmMzNy45LDAsOTIuNywzMC43LDkyLjcsNjguNlYxNDEuN3oiLz4KPC9zdmc%2BCg%3D%3D&colorA=16161d&style=flat-square) + +# Stencil Component Starter + +This is a starter project for building a standalone Web Component using Stencil. + +Stencil is also great for building entire apps. For that, use the [stencil-app-starter](/~https://github.com/ionic-team/stencil-app-starter) instead. + +# Stencil + +Stencil is a compiler for building fast web apps using Web Components. + +Stencil combines the best concepts of the most popular frontend frameworks into a compile-time rather than run-time tool. Stencil takes TypeScript, JSX, a tiny virtual DOM layer, efficient one-way data binding, an asynchronous rendering pipeline (similar to React Fiber), and lazy-loading out of the box, and generates 100% standards-based Web Components that run in any browser supporting the Custom Elements v1 spec. + +Stencil components are just Web Components, so they work in any major framework or with no framework at all. + +## Getting Started + +To start building a new web component using Stencil, clone this repo to a new directory: + +```bash +git clone /~https://github.com/ionic-team/stencil-component-starter.git my-component +cd my-component +git remote rm origin +``` + +and run: + +```bash +npm install +npm start +``` + +To build the component for production, run: + +```bash +npm run build +``` + +To run the unit tests for the components, run: + +```bash +npm test +``` + +Need help? Check out our docs [here](https://stenciljs.com/docs/my-first-component). + + +## Naming Components + +When creating new component tags, we recommend _not_ using `stencil` in the component name (ex: ``). This is because the generated component has little to nothing to do with Stencil; it's just a web component! + +Instead, use a prefix that fits your company or any name for a group of related components. For example, all of the Ionic generated web components use the prefix `ion`. + + +## Using this component + +There are three strategies we recommend for using web components built with Stencil. + +The first step for all three of these strategies is to [publish to NPM](https://docs.npmjs.com/getting-started/publishing-npm-packages). + +### Script tag + +- Put a script tag similar to this `` in the head of your index.html +- Then you can use the element anywhere in your template, JSX, html etc + +### Node Modules +- Run `npm install my-component --save` +- Put a script tag similar to this `` in the head of your index.html +- Then you can use the element anywhere in your template, JSX, html etc + +### In a stencil-starter app +- Run `npm install my-component --save` +- Add an import to the npm packages `import my-component;` +- Then you can use the element anywhere in your template, JSX, html etc diff --git a/my-lib/src/components.d.ts b/my-lib/src/components.d.ts new file mode 100644 index 0000000..cf9e773 --- /dev/null +++ b/my-lib/src/components.d.ts @@ -0,0 +1,61 @@ +/* eslint-disable */ +/* tslint:disable */ +/** + * This is an autogenerated file created by the Stencil compiler. + * It contains typing information for all components that exist in this project. + */ +import { HTMLStencilElement, JSXBase } from "@stencil/core/internal"; +export namespace Components { + interface MyComponent { + /** + * The first name + */ + "first": string; + /** + * The last name + */ + "last": string; + /** + * The middle name + */ + "middle": string; + } +} +declare global { + interface HTMLMyComponentElement extends Components.MyComponent, HTMLStencilElement { + } + var HTMLMyComponentElement: { + prototype: HTMLMyComponentElement; + new (): HTMLMyComponentElement; + }; + interface HTMLElementTagNameMap { + "my-component": HTMLMyComponentElement; + } +} +declare namespace LocalJSX { + interface MyComponent { + /** + * The first name + */ + "first"?: string; + /** + * The last name + */ + "last"?: string; + /** + * The middle name + */ + "middle"?: string; + } + interface IntrinsicElements { + "my-component": MyComponent; + } +} +export { LocalJSX as JSX }; +declare module "@stencil/core" { + export namespace JSX { + interface IntrinsicElements { + "my-component": LocalJSX.MyComponent & JSXBase.HTMLAttributes; + } + } +} diff --git a/my-lib/src/components/my-component/my-component.css b/my-lib/src/components/my-component/my-component.css new file mode 100644 index 0000000..5d4e87f --- /dev/null +++ b/my-lib/src/components/my-component/my-component.css @@ -0,0 +1,3 @@ +:host { + display: block; +} diff --git a/my-lib/src/components/my-component/my-component.e2e.ts b/my-lib/src/components/my-component/my-component.e2e.ts new file mode 100644 index 0000000..d7ff311 --- /dev/null +++ b/my-lib/src/components/my-component/my-component.e2e.ts @@ -0,0 +1,32 @@ +import { newE2EPage } from '@stencil/core/testing'; + +describe('my-component', () => { + it('renders', async () => { + const page = await newE2EPage(); + + await page.setContent(''); + const element = await page.find('my-component'); + expect(element).toHaveClass('hydrated'); + }); + + it('renders changes to the name data', async () => { + const page = await newE2EPage(); + + await page.setContent(''); + const component = await page.find('my-component'); + const element = await page.find('my-component >>> div'); + expect(element.textContent).toEqual(`Hello, World! I'm `); + + component.setProperty('first', 'James'); + await page.waitForChanges(); + expect(element.textContent).toEqual(`Hello, World! I'm James`); + + component.setProperty('last', 'Quincy'); + await page.waitForChanges(); + expect(element.textContent).toEqual(`Hello, World! I'm James Quincy`); + + component.setProperty('middle', 'Earl'); + await page.waitForChanges(); + expect(element.textContent).toEqual(`Hello, World! I'm James Earl Quincy`); + }); +}); diff --git a/my-lib/src/components/my-component/my-component.spec.ts b/my-lib/src/components/my-component/my-component.spec.ts new file mode 100644 index 0000000..c059984 --- /dev/null +++ b/my-lib/src/components/my-component/my-component.spec.ts @@ -0,0 +1,36 @@ +import { newSpecPage } from '@stencil/core/testing'; +import { MyComponent } from './my-component'; + +describe('my-component', () => { + it('renders', async () => { + const { root } = await newSpecPage({ + components: [MyComponent], + html: '', + }); + expect(root).toEqualHtml(` + + +
+ Hello, World! I'm +
+
+
+ `); + }); + + it('renders with values', async () => { + const { root } = await newSpecPage({ + components: [MyComponent], + html: ``, + }); + expect(root).toEqualHtml(` + + +
+ Hello, World! I'm Stencil 'Don't call me a framework' JS +
+
+
+ `); + }); +}); diff --git a/my-lib/src/components/my-component/my-component.tsx b/my-lib/src/components/my-component/my-component.tsx new file mode 100644 index 0000000..56d51d9 --- /dev/null +++ b/my-lib/src/components/my-component/my-component.tsx @@ -0,0 +1,32 @@ +import { Component, Prop, h } from '@stencil/core'; +import { format } from '../../utils/utils'; + +@Component({ + tag: 'my-component', + styleUrl: 'my-component.css', + shadow: true, +}) +export class MyComponent { + /** + * The first name + */ + @Prop() first: string; + + /** + * The middle name + */ + @Prop() middle: string; + + /** + * The last name + */ + @Prop() last: string; + + private getText(): string { + return format(this.first, this.middle, this.last); + } + + render() { + return
Hello, World! I'm {this.getText()}
; + } +} diff --git a/my-lib/src/components/my-component/readme.md b/my-lib/src/components/my-component/readme.md new file mode 100644 index 0000000..06b5864 --- /dev/null +++ b/my-lib/src/components/my-component/readme.md @@ -0,0 +1,19 @@ +# my-component + + + + + + +## Properties + +| Property | Attribute | Description | Type | Default | +| -------- | --------- | --------------- | -------- | ----------- | +| `first` | `first` | The first name | `string` | `undefined` | +| `last` | `last` | The last name | `string` | `undefined` | +| `middle` | `middle` | The middle name | `string` | `undefined` | + + +---------------------------------------------- + +*Built with [StencilJS](https://stenciljs.com/)* diff --git a/my-lib/src/index.html b/my-lib/src/index.html new file mode 100644 index 0000000..d5b0c3e --- /dev/null +++ b/my-lib/src/index.html @@ -0,0 +1,14 @@ + + + + + + Stencil Component Starter + + + + + + + + diff --git a/my-lib/src/index.ts b/my-lib/src/index.ts new file mode 100644 index 0000000..07635cb --- /dev/null +++ b/my-lib/src/index.ts @@ -0,0 +1 @@ +export * from './components'; diff --git a/my-lib/src/utils/utils.spec.ts b/my-lib/src/utils/utils.spec.ts new file mode 100644 index 0000000..81ff970 --- /dev/null +++ b/my-lib/src/utils/utils.spec.ts @@ -0,0 +1,19 @@ +import { format } from './utils'; + +describe('format', () => { + it('returns empty string for no names defined', () => { + expect(format(undefined, undefined, undefined)).toEqual(''); + }); + + it('formats just first names', () => { + expect(format('Joseph', undefined, undefined)).toEqual('Joseph'); + }); + + it('formats first and last names', () => { + expect(format('Joseph', undefined, 'Publique')).toEqual('Joseph Publique'); + }); + + it('formats first, middle and last names', () => { + expect(format('Joseph', 'Quincy', 'Publique')).toEqual('Joseph Quincy Publique'); + }); +}); diff --git a/my-lib/src/utils/utils.ts b/my-lib/src/utils/utils.ts new file mode 100644 index 0000000..4fb9a8b --- /dev/null +++ b/my-lib/src/utils/utils.ts @@ -0,0 +1,3 @@ +export function format(first: string, middle: string, last: string): string { + return (first || '') + (middle ? ` ${middle}` : '') + (last ? ` ${last}` : ''); +} diff --git a/my-lib/stencil.config.ts b/my-lib/stencil.config.ts new file mode 100644 index 0000000..f3ec6f6 --- /dev/null +++ b/my-lib/stencil.config.ts @@ -0,0 +1,21 @@ +import { Config } from '@stencil/core'; + +export const config: Config = { + namespace: 'my-lib', + outputTargets: [ + { + type: 'dist', + esmLoaderPath: '../loader', + }, + { + type: 'dist-custom-elements', + }, + { + type: 'docs-readme', + }, + { + type: 'www', + serviceWorker: null, // disable service workers + }, + ], +}; diff --git a/my-lib/tsconfig.json b/my-lib/tsconfig.json new file mode 100644 index 0000000..09367ce --- /dev/null +++ b/my-lib/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "allowSyntheticDefaultImports": true, + "allowUnreachableCode": false, + "declaration": false, + "experimentalDecorators": true, + "lib": [ + "dom", + "es2017" + ], + "moduleResolution": "node", + "module": "esnext", + "target": "es2017", + "noUnusedLocals": true, + "noUnusedParameters": true, + "jsx": "react", + "jsxFactory": "h" + }, + "include": [ + "src" + ], + "exclude": [ + "node_modules" + ] +}