commit 6e34a0892fac63e6605b79779ff41bdfb124d274 Author: graknar Date: Tue Nov 19 16:07:52 2024 +0100 init with create-stencil v3.5.6 diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..f1cc3ad --- /dev/null +++ b/.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/.gitignore b/.gitignore new file mode 100644 index 0000000..c3ea58a --- /dev/null +++ b/.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/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..7ca3a28 --- /dev/null +++ b/.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/LICENSE b/LICENSE new file mode 100644 index 0000000..b442934 --- /dev/null +++ b/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/package.json b/package.json new file mode 100644 index 0000000..f59defd --- /dev/null +++ b/package.json @@ -0,0 +1,50 @@ +{ + "name": "advancetextbox", + "version": "0.0.1", + "description": "Stencil Component Starter", + "main": "dist/index.cjs.js", + "module": "dist/index.js", + "types": "dist/types/index.d.ts", + "collection": "dist/collection/collection-manifest.json", + "collection:main": "dist/collection/index.js", + "unpkg": "dist/advancetextbox/advancetextbox.esm.js", + "exports": { + ".": { + "import": "./dist/advancetextbox/advancetextbox.esm.js", + "require": "./dist/advancetextbox/advancetextbox.cjs.js" + }, + "./my-component": { + "import": "./dist/components/my-component.js", + "types": "./dist/components/my-component.d.ts" + }, + "./loader": { + "import": "./loader/index.js", + "require": "./loader/index.cjs", + "types": "./loader/index.d.ts" + } + }, + "repository": { + "type": "git", + "url": "https://github.com/ionic-team/stencil-component-starter.git" + }, + "files": [ + "dist/", + "loader/" + ], + "scripts": { + "build": "stencil build", + "start": "stencil build --dev --watch --serve", + "test": "stencil test --spec --e2e", + "test.watch": "stencil test --spec --e2e --watchAll", + "generate": "stencil generate" + }, + "devDependencies": { + "@stencil/core": "^4.7.0", + "@types/jest": "^29.5.6", + "@types/node": "^16.18.11", + "jest": "^29.7.0", + "jest-cli": "^29.7.0", + "puppeteer": "^21.9.0" + }, + "license": "MIT" +} diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..bf619fa --- /dev/null +++ b/readme.md @@ -0,0 +1,115 @@ +[![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)](https://stenciljs.com) + +# 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 runtime 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 two strategies we recommend for using web components built with Stencil. + +The first step for all two of these strategies is to [publish to NPM](https://docs.npmjs.com/getting-started/publishing-npm-packages). + +You can read more about these different approaches in the [Stencil docs](https://stenciljs.com/docs/publishing). + +### Lazy Loading + +If your Stencil project is built with the [`dist`](https://stenciljs.com/docs/distribution) output target, you can import a small bootstrap script that registers all components and allows you to load individual component scripts lazily. + +For example, given your Stencil project namespace is called `my-design-system`, to use `my-component` on any website, inject this into your HTML: + +```html + + + +``` + +This will only load the necessary scripts needed to render ``. Once more components of this package are used, they will automatically be loaded lazily. + +You can also import the script as part of your `node_modules` in your applications entry file: + +```tsx +import 'foobar-design-system/dist/foobar-design-system/foobar-design-system.esm.js'; +``` + +Check out this [Live Demo](https://stackblitz.com/edit/vitejs-vite-y6v26a?file=src%2Fmain.tsx). + +### Standalone + +If you are using a Stencil component library with `dist-custom-elements`, we recommend importing Stencil components individually in those files where they are needed. + +To export Stencil components as standalone components make sure you have the [`dist-custom-elements`](https://stenciljs.com/docs/custom-elements) output target defined in your `stencil.config.ts`. + +For example, given you'd like to use `` as part of a React component, you can import the component directly via: + +```tsx +import 'foobar-design-system/my-component'; + +function App() { + return ( + <> +
+ +
+ + ); +} + +export default App; +``` + +Check out this [Live Demo](https://stackblitz.com/edit/vitejs-vite-b6zuds?file=src%2FApp.tsx). \ No newline at end of file diff --git a/src/components.d.ts b/src/components.d.ts new file mode 100644 index 0000000..cf9e773 --- /dev/null +++ b/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/src/components/my-component/my-component.css b/src/components/my-component/my-component.css new file mode 100644 index 0000000..5d4e87f --- /dev/null +++ b/src/components/my-component/my-component.css @@ -0,0 +1,3 @@ +:host { + display: block; +} diff --git a/src/components/my-component/my-component.e2e.ts b/src/components/my-component/my-component.e2e.ts new file mode 100644 index 0000000..d7ff311 --- /dev/null +++ b/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/src/components/my-component/my-component.spec.ts b/src/components/my-component/my-component.spec.ts new file mode 100644 index 0000000..8075b0d --- /dev/null +++ b/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/src/components/my-component/my-component.tsx b/src/components/my-component/my-component.tsx new file mode 100644 index 0000000..56d51d9 --- /dev/null +++ b/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/src/components/my-component/readme.md b/src/components/my-component/readme.md new file mode 100644 index 0000000..06b5864 --- /dev/null +++ b/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/src/index.html b/src/index.html new file mode 100644 index 0000000..129137c --- /dev/null +++ b/src/index.html @@ -0,0 +1,14 @@ + + + + + + Stencil Component Starter + + + + + + + + diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..fc07dff --- /dev/null +++ b/src/index.ts @@ -0,0 +1,12 @@ +/** + * @fileoverview entry point for your component library + * + * This is the entry point for your component library. Use this file to export utilities, + * constants or data structure that accompany your components. + * + * DO NOT use this file to export your components. Instead, use the recommended approaches + * to consume components of this package as outlined in the `README.md`. + */ + +export { format } from './utils/utils'; +export type * from './components.d.ts'; diff --git a/src/utils/utils.spec.ts b/src/utils/utils.spec.ts new file mode 100644 index 0000000..81ff970 --- /dev/null +++ b/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/src/utils/utils.ts b/src/utils/utils.ts new file mode 100644 index 0000000..b1a0b3d --- /dev/null +++ b/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/stencil.config.ts b/stencil.config.ts new file mode 100644 index 0000000..5e6c06d --- /dev/null +++ b/stencil.config.ts @@ -0,0 +1,26 @@ +import { Config } from '@stencil/core'; + +export const config: Config = { + namespace: 'advancetextbox', + outputTargets: [ + { + type: 'dist', + esmLoaderPath: '../loader', + }, + { + type: 'dist-custom-elements', + customElementsExportBehavior: 'auto-define-custom-elements', + externalRuntime: false, + }, + { + type: 'docs-readme', + }, + { + type: 'www', + serviceWorker: null, // disable service workers + }, + ], + testing: { + browserHeadless: "new", + }, +}; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..09367ce --- /dev/null +++ b/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" + ] +}