Skip to content

Commit 541f580

Browse files
chore: correct linting
1 parent 669630e commit 541f580

File tree

9 files changed

+156
-86
lines changed

9 files changed

+156
-86
lines changed

.eslintignore

+4-1
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,7 @@ _site/
1212
_site-dev
1313
docs/_merged_assets/
1414
docs/_merged_data/
15-
docs/_merged_includes/
15+
docs/_merged_includes/
16+
**/tests/*
17+
*.js
18+
*.d.ts

.eslintrc.js

+6-10
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,17 @@
11
module.exports = {
22
root: true,
33
parser: '@typescript-eslint/parser',
4-
parserOptions: {
5-
tsconfigRootDir: __dirname,
6-
project: ['./tsconfig.json', './packages/**/tsconfig.json']
7-
},
84
plugins: ['simple-import-sort', '@typescript-eslint'],
5+
// extends: [ require.resolve('@open-wc/eslint-config'), require.resolve('eslint-config-prettier')],
96
extends: [
10-
require.resolve('@open-wc/eslint-config'),
11-
require.resolve('eslint-config-prettier'),
12-
],
13-
extends: [
14-
'plugin:@typescript-eslint/recommended', 'prettier', '@open-wc/eslint-config', 'eslint-config-prettier'
7+
'eslint:recommended',
8+
'plugin:@typescript-eslint/eslint-recommended',
9+
'plugin:@typescript-eslint/recommended'
1510
],
1611
rules: {
1712
'lit/no-useless-template-literals': 'off',
1813
'consistent-return': 'off',
1914
'max-classes-per-file': 'off',
15+
'no-prototype-builtins': 'off'
2016
}
21-
};
17+
};

package.json

+4-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@
2525
"@open-wc/eslint-config": "^7.0.0",
2626
"@open-wc/testing": "^3.0.3",
2727
"@types/sinon": "^10.0.6",
28-
"@typescript-eslint/parser": "^5.7.0",
28+
"@typescript-eslint/eslint-plugin": "^5.9.1",
29+
"@typescript-eslint/parser": "^5.9.1",
2930
"@web/dev-server": "^0.1.28",
3031
"@web/dev-server-esbuild": "^0.2.16",
3132
"@web/test-runner": "^0.13.22",
@@ -34,6 +35,8 @@
3435
"construct-style-sheets-polyfill": "^3.0.5",
3536
"element-internals-polyfill": "^0.1.49",
3637
"eslint": "^7.32.0",
38+
"eslint-config-prettier": "^8.3.0",
39+
"eslint-plugin-simple-import-sort": "^7.0.0",
3740
"husky": "^7.0.4",
3841
"lerna": "^4.0.0",
3942
"lint-staged": "^12.1.2",

packages/form-control/src/FormControlMixin.ts

+25-22
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import { IElementInternals } from 'element-internals-polyfill';
22
import { Constructor, FormControlInterface, FormValue, IControlHost, Validator } from './types';
33

4-
export function FormControlMixin<T extends Constructor<HTMLElement & IControlHost>>(SuperClass: T) {
4+
export function FormControlMixin<
5+
TBase extends Constructor<HTMLElement & IControlHost> & { observedAttributes: string[] }
6+
>(SuperClass: TBase) {
57
class FormControl extends SuperClass {
68

79
/** Wires up control instances to be form associated */
@@ -17,6 +19,7 @@ export function FormControlMixin<T extends Constructor<HTMLElement & IControlHos
1719
* be set to an invalid state.
1820
*/
1921
declare static formControlValidators: Validator[];
22+
2023
private static get validators(): Validator[] {
2124
return this.formControlValidators || [];
2225
}
@@ -30,12 +33,11 @@ export function FormControlMixin<T extends Constructor<HTMLElement & IControlHos
3033
static get observedAttributes(): string[] {
3134
const validatorAttributes = this.validators.map((validator) => validator.attribute);
3235

33-
/** @ts-ignore This exits */
3436
const observedAttributes = super.observedAttributes || [];
3537

3638
/** Make sure there are no duplicates inside the attributes list */
3739
const attributeSet = new Set([...observedAttributes, ...validatorAttributes]);
38-
return [...attributeSet];
40+
return [...attributeSet] as string[];
3941
}
4042

4143
/**
@@ -130,6 +132,7 @@ export function FormControlMixin<T extends Constructor<HTMLElement & IControlHos
130132
return this.internals.validity;
131133
}
132134

135+
/* eslint-disable @typescript-eslint/no-explicit-any */
133136
constructor(...args: any[]) {
134137
super(...args);
135138
this.addEventListener('focus', this.#onFocus);
@@ -159,7 +162,9 @@ export function FormControlMixin<T extends Constructor<HTMLElement & IControlHos
159162
/** Initialize the form control and perform initial validation */
160163
this.#initFormControl();
161164
this.#validate(this.value);
162-
this.validationMessageCallback('');
165+
if (this.validationMessageCallback) {
166+
this.validationMessageCallback('');
167+
}
163168
}
164169

165170
disconnectedCallback() {
@@ -181,12 +186,6 @@ export function FormControlMixin<T extends Constructor<HTMLElement & IControlHos
181186
/** Closed over variable to track value changes */
182187
let value: FormValue = this.value || '';
183188

184-
/** Value getter reference within the closure */
185-
let set: ((v: FormValue) => void) | undefined;
186-
187-
/** Value setter reference within the closure */
188-
let get: ((v: FormValue) => void) | undefined;
189-
190189
/** Look to see if '`checked'` is on the control's prototype */
191190
const hasChecked = this.#isCheckedElement;
192191

@@ -210,15 +209,15 @@ export function FormControlMixin<T extends Constructor<HTMLElement & IControlHos
210209
}
211210

212211
/** Make sure to defer to the parent */
213-
set = descriptor && descriptor.set;
214-
get = descriptor && descriptor.get;
212+
const set = descriptor && descriptor.set;
213+
const get = descriptor && descriptor.get;
215214

216215
/** Define the FormControl's value property */
217216
Object.defineProperty(this, 'value', {
218217
get() {
219218
/** If a getter already exists, make sure to call it */
220219
if (get) {
221-
return get.call(this, null);
220+
return get.call(this);
222221
}
223222
return value;
224223
},
@@ -263,8 +262,8 @@ export function FormControlMixin<T extends Constructor<HTMLElement & IControlHos
263262
if (this.constructor.prototype.hasOwnProperty('checked')) {
264263
descriptor = Object.getOwnPropertyDescriptor(this.constructor.prototype, 'checked');
265264
}
266-
let get = descriptor && descriptor.get;
267-
let set = descriptor && descriptor.set;
265+
const get = descriptor && descriptor.get;
266+
const set = descriptor && descriptor.set;
268267

269268
/** Close over the initial value to use in the new getter/setter */
270269
let checked = this.checked;
@@ -312,7 +311,7 @@ export function FormControlMixin<T extends Constructor<HTMLElement & IControlHos
312311
* in cases where `checked` is present upon initialization, this will be
313312
* effectively `this.checked && this.value`.
314313
*/
315-
valueChangedCallback(value: FormValue): void {}
314+
declare valueChangedCallback: (value: FormValue) => void;
316315

317316
/**
318317
* Resets a form control to its initial state
@@ -375,7 +374,9 @@ export function FormControlMixin<T extends Constructor<HTMLElement & IControlHos
375374
this.#forceError = true;
376375
}
377376
const showError = this.#shouldShowError();
378-
this.validationMessageCallback(showError ? this.validationMessage : '');
377+
if (this.validationMessageCallback) {
378+
this.validationMessageCallback(showError ? this.validationMessage : '');
379+
}
379380
};
380381

381382
/**
@@ -400,7 +401,9 @@ export function FormControlMixin<T extends Constructor<HTMLElement & IControlHos
400401
}
401402
this.#validate(value);
402403
const showError = this.#shouldShowError();
403-
this.validationMessageCallback(showError ? this.validationMessage : '');
404+
if (this.validationMessageCallback) {
405+
this.validationMessageCallback(showError ? this.validationMessage : '');
406+
}
404407
}
405408

406409
/**
@@ -443,7 +446,7 @@ export function FormControlMixin<T extends Constructor<HTMLElement & IControlHos
443446
* if a control has a ValidityCallback, it can override the error
444447
* message for a given validity key.
445448
*/
446-
if (this.validityCallback(key)) {
449+
if (this.validityCallback && this.validityCallback(key)) {
447450
messageResult = this.validityCallback(key) as string;
448451
} else if (message instanceof Function) {
449452
messageResult = message(this, value);
@@ -508,14 +511,14 @@ export function FormControlMixin<T extends Constructor<HTMLElement & IControlHos
508511
* The returned value will be used as the validationMessage for the given key.
509512
* @param validationKey {string} - The key that has returned invalid
510513
*/
511-
validityCallback(validationKey: string): string | void {}
514+
declare validityCallback: (validationKey: string) => string | void;
512515

513516
/**
514517
* Called when the control's validationMessage should be changed
515518
* @param message { string } - The new validation message
516519
*/
517-
validationMessageCallback(message: string): void {}
520+
declare validationMessageCallback: (message: string) => void;
518521
}
519522

520-
return FormControl as Constructor<FormControlInterface> & T;
523+
return FormControl as Constructor<FormControlInterface> & TBase;
521524
}

packages/form-control/src/types.ts

+8-7
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { IElementInternals } from 'element-internals-polyfill';
22

33
/** Generic constructor type */
4-
export type Constructor<T = {}> = new (...args: any[]) => T;
4+
/* eslint-disable @typescript-eslint/no-explicit-any */
5+
export type Constructor<T = Record<string, unknown>> = new (...args: any[]) => T;
56

67
/** Union type for form values */
78
export type FormValue = File|FormData|string|null;
@@ -10,7 +11,7 @@ export type FormValue = File|FormData|string|null;
1011
export interface FormControlInterface {
1112
checked?: boolean;
1213
validationTarget?: HTMLElement | null;
13-
value: any;
14+
value: FormValue;
1415
readonly form: HTMLFormElement;
1516
readonly internals: IElementInternals;
1617
readonly showError: boolean;
@@ -20,7 +21,7 @@ export interface FormControlInterface {
2021
checkValidity(): boolean;
2122
formResetCallback(): void;
2223
resetFormControl(): void;
23-
valueChangedCallback(value: any): void;
24+
valueChangedCallback(value: FormValue): void;
2425
validityCallback(validationKey: string): string | void;
2526
validationMessageCallback(message: string): void;
2627
}
@@ -64,22 +65,22 @@ export interface Validator {
6465
* ValidityState key as an argument and must return a validationMessage
6566
* for the given instance.
6667
*/
67-
message: string | ((instance: any, value: any) => string);
68+
message: string | ((instance: any, value: FormValue) => string);
6869

6970
/**
7071
* Callback for a given validator. Takes the FormControl instance
7172
* and the form control value as arguments and returns a
7273
* boolean to evaluate for that Validator.
7374
* @param instance {FormControlInterface} - The FormControl instance
74-
* @param value {any} - The form control value
75+
* @param value {FormValue} - The form control value
7576
* @returns {boolean} - The validity of a given Validator
7677
*/
77-
callback(instance: HTMLElement, value: any): boolean;
78+
callback(instance: HTMLElement, value: FormValue): boolean;
7879
}
7980

8081
/** Generic type to allow usage of HTMLElement lifecycle methods */
8182
export interface IControlHost {
82-
attributeChangedCallback?(name: string, oldValue: any, newValue: any): void;
83+
attributeChangedCallback?(name: string, oldValue: string, newValue: string): void;
8384
connectedCallback?(): void;
8485
disconnectedCallback?(): void;
8586
checked?: boolean;

packages/form-control/src/validators.ts

+9-7
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { Validator } from './index';
2-
import { FormControlInterface } from './types';
2+
import { FormControlInterface, FormValue } from './types';
33

44
export const requiredValidator: Validator = {
55
attribute: 'required',
66
key: 'valueMissing',
77
message: 'Please fill out this field',
8-
callback(instance: HTMLElement & { required: boolean }, value: any): boolean {
8+
callback(instance: HTMLElement & { required: boolean }, value: FormValue): boolean {
99
let valid = true;
1010

1111
if ((instance.hasAttribute('required') || instance.required) && !value) {
@@ -30,9 +30,10 @@ export const minLengthValidator: Validator = {
3030
attribute: 'minlength',
3131
key: 'rangeUnderflow',
3232
message(instance: FormControlInterface & { minLength: number }): string {
33-
return `Please use at least ${instance.minLength} characters (you are currently using ${instance.value.length} characters).`;
33+
const value = instance.value as string || '';
34+
return `Please use at least ${instance.minLength} characters (you are currently using ${value.length} characters).`;
3435
},
35-
callback(instance: HTMLElement & { minLength: number }, value): boolean {
36+
callback(instance: HTMLElement & { minLength: number }, value: string): boolean {
3637
/** If no value is provided, this validator should return true */
3738
if (!value) {
3839
return true;
@@ -52,11 +53,12 @@ export const maxLengthValidator: Validator = {
5253
message(
5354
instance: FormControlInterface & { maxLength: number }
5455
): string {
55-
return `Please use no more than ${instance.maxLength} characters (you are currently using ${instance.value.length} characters).`;
56+
const value = instance.value as string || '';
57+
return `Please use no more than ${instance.maxLength} characters (you are currently using ${value.length} characters).`;
5658
},
5759
callback(
5860
instance: HTMLElement & { maxLength: number },
59-
value: any
61+
value: string
6062
): boolean {
6163
/** If maxLength isn't set, this is valid */
6264
if (!instance.maxLength) {
@@ -75,7 +77,7 @@ export const patternValidator: Validator = {
7577
attribute: 'pattern',
7678
key: 'patternMismatch',
7779
message: 'Please match the requested format',
78-
callback(instance: HTMLElement & { pattern: string }, value): boolean {
80+
callback(instance: HTMLElement & { pattern: string }, value: string): boolean {
7981
/** If no value is provided, this validator should return true */
8082
if (!value || !instance.pattern) {
8183
return true;

packages/form-helpers/src/index.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export const formValues = (form: HTMLFormElement): Record<string, FormValue> =>
3333
const formData = new FormData(form);
3434
const values: Record<string, FormValue> = {};
3535

36-
for (let [key, value] of formData.entries()) {
36+
for (const [key, value] of formData.entries()) {
3737
if (!values.hasOwnProperty(key)) {
3838
values[key] = value;
3939
} else if (Array.isArray(values[key])) {
@@ -58,11 +58,11 @@ export const formValues = (form: HTMLFormElement): Record<string, FormValue> =>
5858
* in declaratively in HTML.
5959
*
6060
* @param form {HTMLFormElement} - The form to grab values from
61-
* @returns {Object<any, any>} - An object representation of the form
61+
* @returns {Object<string, FormValue>} - An object representation of the form
6262
*/
6363
export const parseFormAsObject = (form: HTMLFormElement): Record<string, FormValue> => {
6464
const data = formValues(form);
65-
const output: Record<any, any> = {};
65+
const output: Record<string, FormValue> = {};
6666

6767
Object.entries(data).forEach(([key, value]) => {
6868
/** If the key has a '.', parse it as an object */
@@ -73,8 +73,8 @@ export const parseFormAsObject = (form: HTMLFormElement): Record<string, FormVal
7373

7474
while (path.length) {
7575
const key = path.shift();
76-
pointer[key as string] = pointer[key as string] || {};
77-
pointer = pointer[key as string];
76+
pointer[key as string] = pointer[key as string] || ({} as FormValue);
77+
pointer = pointer[key as string] as unknown as Record<string, FormValue>;
7878
}
7979

8080
pointer[destination as string] = value;

packages/form-helpers/tests/submit.test.ts

+3-4
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const submitCallbackPrevented = (event: Event) => {
77
event.preventDefault();
88
submitted = true;
99
};
10-
const submitCallback = (event: Event) => {
10+
const submitCallback = () => {
1111
submitted = true;
1212
};
1313

@@ -19,7 +19,7 @@ describe('The submit form helper', () => {
1919
form = await fixture<HTMLFormElement>(html`<form @submit="${submitCallback}">
2020
<input>
2121
</form>`);
22-
formSubmitStub = sinon.stub(form, 'submit').callsFake(() => {});
22+
formSubmitStub = sinon.stub(form, 'submit').callsFake(() => { return false; });
2323
submitted = false;
2424
});
2525

@@ -32,7 +32,6 @@ describe('The submit form helper', () => {
3232
submit(form);
3333
await aTimeout(0);
3434
expect(submitted).to.be.true;
35-
// form.submit() is called
3635
expect(formSubmitStub.callCount).to.equal(1);
3736
});
3837

@@ -56,7 +55,7 @@ describe('The submit form helper', () => {
5655
<input>
5756
</form>`);
5857

59-
formSubmitStub = sinon.stub(form, 'submit').callsFake(() => {});
58+
formSubmitStub = sinon.stub(form, 'submit').callsFake(() => { return false; });
6059

6160
submit(form);
6261

0 commit comments

Comments
 (0)