diff --git a/components/filter/test/golden/filter/chromium/single-set-searched-search-then-clear.png b/components/filter/test/golden/filter/chromium/single-set-searched-search-then-clear.png index a76f7c223a6..49d7067c3f4 100644 Binary files a/components/filter/test/golden/filter/chromium/single-set-searched-search-then-clear.png and b/components/filter/test/golden/filter/chromium/single-set-searched-search-then-clear.png differ diff --git a/jsconfig.json b/jsconfig.json new file mode 100644 index 00000000000..5de68b6328b --- /dev/null +++ b/jsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "module": "ES2020", + "target": "ES2020", + "typeRoots": ["./typings", "./node_modules/@types"], + "checkJs": false, + "moduleResolution": "bundler" + }, + "include": ["**/*", "**/*.js"], + "exclude": ["node_modules", "./tools/**/*"] +} diff --git a/package.json b/package.json index 32489b6ce87..75f2899f817 100644 --- a/package.json +++ b/package.json @@ -13,11 +13,15 @@ "build:illustrations": "node ./cli/empty-state-illustration-generator.js", "build:sass": "sass ./test/sass.scss > ./test/sass.output.css", "build:wca": "wca analyze \"{components,templates}/**/*.js\" --format json --outFile custom-elements.json", - "build": "npm run build:clean && npm run build:icons && npm run build:illustrations && npm run build:sass && npm run build:wca", + "build:lit-mappings": "sh ./tools/create-mapping.sh", + "build": "npm run build:clean && npm run build:icons && npm run build:illustrations && npm run build:sass && npm run build:wca && npm run build:lit-mappings", "build-static": "rollup -c ./rollup/rollup.config.js", - "lint": "npm run lint:eslint && npm run lint:style", + "lint": "npm run lint:eslint && npm run lint:style && npm run lint:types", "lint:eslint": "eslint .", "lint:style": "stylelint \"**/*.{js,html}\" --ignore-path .gitignore", + "prelint:types": "cp typings/mapping.d.ts typings/mapping.ts", + "lint:types": "tsc -p tools/check-html-element-tag-types/tsconfig.json", + "postlint:types": "rm typings/mapping.ts", "start": "web-dev-server --node-resolve --watch --open", "test": "npm run lint && npm run test:translations && npm run test:unit && npm run test:axe", "test:axe": "d2l-test-runner axe --chrome", @@ -37,11 +41,13 @@ "/mixins", "/templates", "/tools", + "/typings/mapping.d.ts", "!demo", "!test", "/components/demo", "!/components/demo/demo" ], + "types": "./typings/mapping.d.ts", "author": "D2L Corporation", "license": "Apache-2.0", "devDependencies": { diff --git a/tools/check-html-element-tag-types/check-html-element-helper.d.ts b/tools/check-html-element-tag-types/check-html-element-helper.d.ts new file mode 100644 index 00000000000..afdd798c3ec --- /dev/null +++ b/tools/check-html-element-tag-types/check-html-element-helper.d.ts @@ -0,0 +1,13 @@ +/** + * Set Element constructors to something generic so that check-html-element-tag-types + * will fail if one of the classes in the mixin chain doesn't extend HTMLElement. + * Otherwise, the mixins will default to the element mixin + */ +import { Constructor } from '@open-wc/dedupe-mixin'; + +declare global { + type LitElementConstructor = Constructor<{}>; + type LitElementClassType = Constructor<{}>; + type ReactiveElementConstructor = Constructor<{}>; + type ReactiveElementClassType = Constructor<{}>; +} diff --git a/tools/check-html-element-tag-types/check-html-element-tag-types.ts b/tools/check-html-element-tag-types/check-html-element-tag-types.ts new file mode 100644 index 00000000000..523c9223c9c --- /dev/null +++ b/tools/check-html-element-tag-types/check-html-element-tag-types.ts @@ -0,0 +1,6 @@ +/// +/// + +type Check = K; +// This line fails if the mapping contains something that doesn't extend HTMLElement +type Test = Check; diff --git a/tools/check-html-element-tag-types/tsconfig.json b/tools/check-html-element-tag-types/tsconfig.json new file mode 100644 index 00000000000..366567814af --- /dev/null +++ b/tools/check-html-element-tag-types/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "module": "ES2020", + "target": "ES2020", + "allowJs": true, + "checkJs": false, + "noEmit": true, + "strict": true, + "strictFunctionTypes": false, + "moduleResolution": "bundler", + "maxNodeModuleJsDepth": 3, + "skipLibCheck": true + }, + "files": ["check-html-element-tag-types.ts"] + } + \ No newline at end of file diff --git a/tools/create-mapping.sh b/tools/create-mapping.sh new file mode 100644 index 00000000000..6aea704ca45 --- /dev/null +++ b/tools/create-mapping.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +FILES=`egrep --include="*.js" --exclude-dir="node_modules" --exclude-dir="test" -lR "customElements.define" * | xargs egrep -L 'export class.*Test.* extends'` + +FILES_WITH_TYPEDEF=`egrep -l "@typedef.*Exported" $FILES` +FILES_WITH_EXPORT=`egrep -l "export class.*" $FILES` + +echo "/** Generated from {@link ../tools/create-mapping.sh} */" > ./typings/mapping.d.ts +echo "import { LitElement } from 'lit';" >> ./typings/mapping.d.ts +echo "declare global {" >> ./typings/mapping.d.ts +echo " interface HTMLElementTagNameMap {" >> ./typings/mapping.d.ts +if [ "x$FILES_WITH_TYPEDEF" != "x" ] +then + echo " // Components with @typedef exports" >> ./typings/mapping.d.ts + egrep -oR "customElements.define\(['\"].*\)" $FILES_WITH_TYPEDEF | sed -r "s/(.*):customElements\.define\((.*),\s*(.*)\)/ \2: import('..\/\1').\3Exported;/" >> ./typings/mapping.d.ts +fi +if [ "x$FILES_WITH_EXPORT" != "x" ] +then + echo " // Components with export class...extends LitElement" >> ./typings/mapping.d.ts + egrep -oR "customElements.define\(['\"].*\)" $FILES_WITH_EXPORT | sed -r "s/(.*):customElements\.define\((.*),\s*(.*)\)/ \2: import('..\/\1').\3;/" >> ./typings/mapping.d.ts +fi +echo " }" >> ./typings/mapping.d.ts +echo "}" >> ./typings/mapping.d.ts diff --git a/typings/common.d.ts b/typings/common.d.ts new file mode 100644 index 00000000000..c09df036155 --- /dev/null +++ b/typings/common.d.ts @@ -0,0 +1,14 @@ +import { Constructor } from '@open-wc/dedupe-mixin'; +import { LitElement, ReactiveElement } from 'lit'; + +declare global { + // Used for mixins that use lit-html but don't set properties or styles + type LitElementConstructor = Constructor; + // Used for mixins that use lit-html and set properties or styles + type LitElementClassType = LitElementConstructor & Pick; + + // Used for mixins that use reactive element properties (updated, willUpdate, firstUpdated, connectedCallback, etc) but don't set properties or styles + type ReactiveElementConstructor = Constructor; + // Used for mixins that use reactive element properties (updated, willUpdate, firstUpdated, connectedCallback, etc) and set properties or styles + type ReactiveElementClassType = ReactiveElementConstructor & Pick; +} diff --git a/typings/mapping.d.ts b/typings/mapping.d.ts new file mode 100644 index 00000000000..b011c509c61 --- /dev/null +++ b/typings/mapping.d.ts @@ -0,0 +1,8 @@ +/** Generated from {@link ../tools/create-mapping.sh} */ +import { LitElement } from 'lit'; +declare global { + interface HTMLElementTagNameMap { + // Components with export class...extends LitElement + 'd2l-build-info': import('../index.js').BuildInfo; + } +}