From 83f7c1b9031b0490f982dedbf50c786381d931b0 Mon Sep 17 00:00:00 2001 From: Benny Powers Date: Sun, 7 Jul 2024 13:38:30 +0300 Subject: [PATCH 1/4] chore: lint massive lint. no more warnings --- .../controllers/cascade-controller.ts | 9 +- .../controllers/floating-dom-controller.ts | 9 +- .../controllers/internals-controller.ts | 6 +- .../controllers/listbox-controller.ts | 18 +++- core/pfe-core/controllers/logger.ts | 12 ++- .../controllers/roving-tabindex-controller.ts | 12 ++- .../controllers/scroll-spy-controller.ts | 5 +- core/pfe-core/controllers/slot-controller.ts | 27 +++--- .../controllers/tabs-aria-controller.ts | 2 + core/pfe-core/decorators/bound.ts | 4 +- core/pfe-core/decorators/cascades.ts | 3 +- core/pfe-core/decorators/deprecation.ts | 11 ++- core/pfe-core/decorators/observed.ts | 31 +++--- core/pfe-core/decorators/trace.ts | 5 +- core/pfe-core/functions/containsDeep.ts | 2 + core/pfe-core/functions/context.ts | 1 + docs/_plugins/cem-render.cjs | 96 ++++++++++++++----- docs/_plugins/pfe-assets.cjs | 7 +- .../pf-accordion/test/pf-accordion.spec.ts | 4 - elements/pf-button/demo/block.html | 1 - elements/pf-button/demo/sizes.html | 1 - elements/pf-button/demo/variants.html | 1 - elements/pf-chip/pf-chip-group.ts | 3 + elements/pf-dropdown/pf-dropdown-item.ts | 2 - elements/pf-dropdown/pf-dropdown-menu.ts | 2 + elements/pf-icon/pf-icon.ts | 7 +- elements/pf-icon/test/pf-icon.spec.ts | 2 +- elements/pf-modal/pf-modal.ts | 1 + elements/pf-popover/pf-popover.ts | 1 + elements/pf-popover/test/pf-popover.spec.ts | 14 +-- .../pf-progress-stepper.ts | 1 - elements/pf-select/pf-select.ts | 8 +- elements/pf-tooltip/pf-tooltip.ts | 1 + playwright.config.ts | 2 +- scripts/bundle-release.cjs | 17 +--- scripts/bundle.js | 4 + scripts/format-commitlint-messages.js | 6 ++ scripts/format-lighthouse.cjs | 1 - tools/create-element/generator/element.ts | 7 +- tools/create-element/generator/files.ts | 20 +++- tools/create-element/generator/fp.ts | 5 +- tools/create-element/main.ts | 6 ++ tools/eslint-config/configs/pfe.js | 28 +++++- tools/netlify-plugin-github-actions/index.js | 7 ++ tools/pfe-tools/config.ts | 6 ++ .../custom-elements-manifest/config.ts | 3 +- .../custom-elements-manifest/demos.ts | 1 + .../ecma-private-class-members.ts | 3 + .../jsdoc-description-default.ts | 5 + .../custom-elements-manifest/lib/Manifest.ts | 10 ++ .../lib/get-all-packages.ts | 5 + .../version-static-field.ts | 3 + tools/pfe-tools/dev-server/config.ts | 13 ++- .../plugins/import-map-generator.ts | 3 + tools/pfe-tools/environment.ts | 6 ++ tools/pfe-tools/react/generate-wrappers.ts | 21 +++- tools/pfe-tools/ssr/ssr.ts | 3 + tools/pfe-tools/test/a11y-snapshot.ts | 3 + tools/pfe-tools/test/config.ts | 9 +- tools/pfe-tools/test/get-composed-text.ts | 1 + tools/pfe-tools/test/hex-to-rgb.ts | 11 ++- .../pfe-tools/test/playwright/PfeDemoPage.ts | 24 ++++- tools/pfe-tools/test/render-to-string.ts | 4 + tools/pfe-tools/test/utils.ts | 11 ++- .../typescript/transformers/css-imports.cjs | 15 +-- 65 files changed, 426 insertions(+), 146 deletions(-) diff --git a/core/pfe-core/controllers/cascade-controller.ts b/core/pfe-core/controllers/cascade-controller.ts index c7a285c033..d79ef0b842 100644 --- a/core/pfe-core/controllers/cascade-controller.ts +++ b/core/pfe-core/controllers/cascade-controller.ts @@ -5,7 +5,7 @@ import { debounce } from '../functions/debounce.js'; import { Logger } from './logger.js'; /** - * @deprecated: use context, especially via `@patternfly/pfe-core/functions/context.js`; + * @deprecated use context, especially via `@patternfly/pfe-core/functions/context.js`; */ export interface Options { properties: Partial>; @@ -13,7 +13,7 @@ export interface Options { } /** - * @deprecated: use context, especially via `@patternfly/pfe-core/functions/context.js`; + * @deprecated use context, especially via `@patternfly/pfe-core/functions/context.js`; */ export class CascadeController implements ReactiveController { private class: typeof ReactiveElement; @@ -54,6 +54,7 @@ export class CascadeController implements ReactiveCon /** * Handles the cascading of properties to nested components when new elements are added * Attribute updates/additions are handled by the attribute callback + * @param [nodeList=this.host.children] */ cascadeProperties(nodeList: HTMLCollection | NodeList = this.host.children) { if (this.host.isConnected) { @@ -89,6 +90,8 @@ export class CascadeController implements ReactiveCon * Gets the configured attribute name for the decorated property, * falling back to the lowercased property name, and caches the attribute name * with it's designated child selectors for value-propagation on change + * @param propName + * @param cascade */ initProp(propName: string, cascade: string | string[]) { for (const nodeItem of [cascade].flat(Infinity).filter(Boolean) as string[]) { @@ -122,6 +125,8 @@ export class CascadeController implements ReactiveCon /** * Copy the named attribute to a target element. + * @param name attr name + * @param el element */ private async _copyAttribute(name: string, el: Element) { this.logger.log(`copying ${name} to ${el}`); diff --git a/core/pfe-core/controllers/floating-dom-controller.ts b/core/pfe-core/controllers/floating-dom-controller.ts index 4522c0ec94..5638e0d9f7 100644 --- a/core/pfe-core/controllers/floating-dom-controller.ts +++ b/core/pfe-core/controllers/floating-dom-controller.ts @@ -167,7 +167,14 @@ export class FloatingDOMController implements ReactiveController { this.host.requestUpdate(); } - /** Show the floating DOM */ + /** + * Show the floating DOM + * @param [options={}] + * @param options.offset + * @param options.placement + * @param options.flip + * @param options.fallbackPlacements + * */ async show({ offset, placement, flip, fallbackPlacements }: ShowOptions = {}) { const invoker = this.#invoker; const content = this.#content; diff --git a/core/pfe-core/controllers/internals-controller.ts b/core/pfe-core/controllers/internals-controller.ts index 3b994d4ed6..f4bd13a1d8 100644 --- a/core/pfe-core/controllers/internals-controller.ts +++ b/core/pfe-core/controllers/internals-controller.ts @@ -21,7 +21,11 @@ interface InternalsControllerOptions extends Partial { getHTMLElement?(): HTMLElement; } -/** reactively forward the internals object's aria mixin prototype */ +/** + * reactively forward the internals object's aria mixin prototype + * @param target + * @param key + */ function aria( target: InternalsController, key: keyof InternalsController, diff --git a/core/pfe-core/controllers/listbox-controller.ts b/core/pfe-core/controllers/listbox-controller.ts index abcda1ec6f..ec147a8e50 100644 --- a/core/pfe-core/controllers/listbox-controller.ts +++ b/core/pfe-core/controllers/listbox-controller.ts @@ -33,17 +33,17 @@ let constructingAllowed = false; * ActiveDescendantController) to complete the implementation. */ export class ListboxController implements ReactiveController { - private static instances = new WeakMap>(); + private static instances = new WeakMap>(); public static of( host: ReactiveControllerHost, options: ListboxConfigOptions, ): ListboxController { constructingAllowed = true; - const instance: ListboxController = + const instance = ListboxController.instances.get(host) ?? new ListboxController(host, options); constructingAllowed = false; - return instance; + return instance as ListboxController; } private constructor( @@ -162,6 +162,7 @@ export class ListboxController implements ReactiveCont /** * handles focusing on an option: * updates roving tabindex and active descendant + * @param event focus event */ #onFocus = (event: FocusEvent) => { const target = this.#getEventOption(event); @@ -174,6 +175,7 @@ export class ListboxController implements ReactiveCont * handles clicking on a listbox option: * which selects an item by default * or toggles selection if multiselectable + * @param event click event */ #onClick = (event: MouseEvent) => { const target = this.#getEventOption(event); @@ -199,8 +201,8 @@ export class ListboxController implements ReactiveCont }; /** - * handles keyup: * track whether shift key is being used for multiselectable listbox + * @param event keyup event */ #onKeyup = (event: KeyboardEvent) => { const target = this.#getEventOption(event); @@ -215,9 +217,9 @@ export class ListboxController implements ReactiveCont }; /** - * handles keydown: * filters listbox by keyboard event when slotted option has focus, * or by external element such as a text field + * @param event keydown event */ #onKeydown = (event: KeyboardEvent) => { const target = this.#getEventOption(event); @@ -265,6 +267,7 @@ export class ListboxController implements ReactiveCont /** * handles change to options given previous options array + * @param oldOptions previous options list */ #optionsChanged(oldOptions: Item[]) { const setSize = this.#items.length; @@ -291,6 +294,9 @@ export class ListboxController implements ReactiveCont /** * updates option selections for multiselectable listbox: * toggles all options between active descendant and target + * @param currentItem item being added + * @param referenceItem item already selected. + * @param ctrlA is ctrl-a held down? */ #updateMultiselect( currentItem?: Item, @@ -322,6 +328,7 @@ export class ListboxController implements ReactiveCont /** * sets the listbox value based on selected options + * @param value item or items */ setValue(value: Item | Item[]) { const selected = Array.isArray(value) ? value : [value]; @@ -336,6 +343,7 @@ export class ListboxController implements ReactiveCont /** * register's the host's Item elements as listbox controller items + * @param options items */ setOptions(options: Item[]) { const oldOptions = [...this.#items]; diff --git a/core/pfe-core/controllers/logger.ts b/core/pfe-core/controllers/logger.ts index 4c4cb7bfd3..4e5bad5ef2 100644 --- a/core/pfe-core/controllers/logger.ts +++ b/core/pfe-core/controllers/logger.ts @@ -17,7 +17,7 @@ export class Logger implements ReactiveController { * A boolean value that indicates if the logging should be printed to the console; used for debugging. * For use in a JS file or script tag; can also be added in the constructor of a component during development. * @example Logger.debugLog(true); - * @tags debug + * @param [preference=null] */ static debugLog(preference = null) { // wrap localStorage references in a try/catch; merely referencing it can @@ -38,6 +38,7 @@ export class Logger implements ReactiveController { /** * A logging wrapper which checks the debugLog boolean and prints to the console if true. * @example Logger.debug("Hello"); + * @param msgs console.log params */ static debug(...msgs: unknown[]) { if (Logger.debugLog()) { @@ -48,6 +49,7 @@ export class Logger implements ReactiveController { /** * A logging wrapper which checks the debugLog boolean and prints to the console if true. * @example Logger.info("Hello"); + * @param msgs console.log params */ static info(...msgs: unknown[]) { if (Logger.debugLog()) { @@ -58,6 +60,7 @@ export class Logger implements ReactiveController { /** * A logging wrapper which checks the debugLog boolean and prints to the console if true. * @example Logger.log("Hello"); + * @param msgs console.log params */ static log(...msgs: unknown[]) { if (Logger.debugLog()) { @@ -68,6 +71,7 @@ export class Logger implements ReactiveController { /** * A console warning wrapper which formats your output with useful debugging information. * @example Logger.warn("Hello"); + * @param msgs console.log params */ static warn(...msgs: unknown[]) { console.warn(...msgs); @@ -77,6 +81,7 @@ export class Logger implements ReactiveController { * A console error wrapper which formats your output with useful debugging information. * For use inside a component's function. * @example Logger.error("Hello"); + * @param msgs console.log params */ static error(...msgs: unknown[]) { console.error([...msgs].join(' ')); @@ -87,6 +92,7 @@ export class Logger implements ReactiveController { /** * Debug logging that outputs the tag name as a prefix automatically * @example this.logger.log("Hello"); + * @param msgs console.log params */ debug(...msgs: unknown[]) { Logger.debug(this.prefix, ...msgs); @@ -95,6 +101,7 @@ export class Logger implements ReactiveController { /** * Info logging that outputs the tag name as a prefix automatically * @example this.logger.log("Hello"); + * @param msgs console.log params */ info(...msgs: unknown[]) { Logger.info(this.prefix, ...msgs); @@ -103,6 +110,7 @@ export class Logger implements ReactiveController { /** * Local logging that outputs the tag name as a prefix automatically * @example this.logger.log("Hello"); + * @param msgs console.log params */ log(...msgs: unknown[]) { Logger.log(this.prefix, ...msgs); @@ -112,6 +120,7 @@ export class Logger implements ReactiveController { * Local warning wrapper that outputs the tag name as a prefix automatically. * For use inside a component's function. * @example this.logger.warn("Hello"); + * @param msgs console.log params */ warn(...msgs: unknown[]) { Logger.warn(this.prefix, ...msgs); @@ -121,6 +130,7 @@ export class Logger implements ReactiveController { * Local error wrapper that outputs the tag name as a prefix automatically. * For use inside a component's function. * @example this.logger.error("Hello"); + * @param msgs console.log params */ error(...msgs: unknown[]) { Logger.error(this.prefix, ...msgs); diff --git a/core/pfe-core/controllers/roving-tabindex-controller.ts b/core/pfe-core/controllers/roving-tabindex-controller.ts index 133cce7bab..b8c64fc652 100644 --- a/core/pfe-core/controllers/roving-tabindex-controller.ts +++ b/core/pfe-core/controllers/roving-tabindex-controller.ts @@ -179,6 +179,7 @@ export class RovingTabindexController< /** * handles keyboard navigation + * @param event keydown event */ #onKeydown = (event: Event) => { if (!(event instanceof KeyboardEvent) @@ -250,6 +251,7 @@ export class RovingTabindexController< /** * Sets the active item and focuses it + * @param item tabindex item */ setActiveItem(item?: Item): void { this.#activeItem = item; @@ -264,6 +266,7 @@ export class RovingTabindexController< /** * Focuses next focusable item + * @param items tabindex items */ updateItems(items: Item[] = this.#options.getItems?.() ?? []) { this.#items = items; @@ -277,14 +280,19 @@ export class RovingTabindexController< this.setActiveItem(activeItem); } - /** @deprecated use setActiveItem */ + /** + * @deprecated use setActiveItem + * @param item tabindex item + */ focusOnItem(item?: Item): void { this.setActiveItem(item); } /** * from array of HTML items, and sets active items - * @deprecated: use getItems and getItemContainer option functions + * @deprecated use getItems and getItemContainer option functions + * @param items tabindex items + * @param itemsContainer */ initItems(items: Item[], itemsContainer?: Element) { const element = itemsContainer diff --git a/core/pfe-core/controllers/scroll-spy-controller.ts b/core/pfe-core/controllers/scroll-spy-controller.ts index 9468b3a547..a53b4d2fa5 100644 --- a/core/pfe-core/controllers/scroll-spy-controller.ts +++ b/core/pfe-core/controllers/scroll-spy-controller.ts @@ -153,7 +153,10 @@ export class ScrollSpyController implements ReactiveController { this.#intersected = true; } - /** Explicitly set the active item */ + /** + * Explicitly set the active item + * @param link usually an `` + */ public async setActive(link: EventTarget | null) { this.#force = true; this.#setActive(link); diff --git a/core/pfe-core/controllers/slot-controller.ts b/core/pfe-core/controllers/slot-controller.ts index c271797715..2dc7b54e25 100644 --- a/core/pfe-core/controllers/slot-controller.ts +++ b/core/pfe-core/controllers/slot-controller.ts @@ -41,6 +41,7 @@ function isObjectConfigSpread( /** * If it's a named slot, return its children, * for the default slot, look for direct children not assigned to a slot + * @param n slot name */ const isSlot = (n: string | typeof SlotController.default) => @@ -112,18 +113,19 @@ export class SlotController implements ReactiveController { /** * Given a slot name or slot names, returns elements assigned to the requested slots as an array. * If no value is provided, it returns all children not assigned to a slot (without a slot attribute). + * @param slotNames slots to query * @example Get header-slotted elements - * ```js - * this.getSlotted('header') - * ``` + * ```js + * this.getSlotted('header') + * ``` * @example Get header- and footer-slotted elements - * ```js - * this.getSlotted('header', 'footer') - * ``` + * ```js + * this.getSlotted('header', 'footer') + * ``` * @example Get default-slotted elements - * ```js - * this.getSlotted(); - * ``` + * ```js + * this.getSlotted(); + * ``` */ getSlotted(...slotNames: string[]): T[] { if (!slotNames.length) { @@ -140,17 +142,16 @@ export class SlotController implements ReactiveController { * @example this.hasSlotted('header'); */ hasSlotted(...names: (string | null | undefined)[]): boolean { - const { anonymous } = SlotController; - const slotNames = Array.from(names, x => x == null ? anonymous : x); + const slotNames = Array.from(names, x => x == null ? SlotController.default : x); if (!slotNames.length) { - slotNames.push(anonymous); + slotNames.push(SlotController.default); } return slotNames.some(x => this.#nodes.get(x)?.hasContent ?? false); } /** * Whether or not all the requested slots are empty. - * @param slots The slot name. If no value is provided, it returns the default slot. + * @param names The slot names to query. If no value is provided, it returns the default slot. * @example this.isEmpty('header', 'footer'); * @example this.isEmpty(); * @returns diff --git a/core/pfe-core/controllers/tabs-aria-controller.ts b/core/pfe-core/controllers/tabs-aria-controller.ts index 93bb25659e..176b8b1403 100644 --- a/core/pfe-core/controllers/tabs-aria-controller.ts +++ b/core/pfe-core/controllers/tabs-aria-controller.ts @@ -36,6 +36,8 @@ export class TabsAriaController< } /** + * @param host controller host + * @param options controller options * @example Usage in PfTab * ```ts * new TabsController(this, { diff --git a/core/pfe-core/decorators/bound.ts b/core/pfe-core/decorators/bound.ts index 11b87835e0..458b94cabe 100644 --- a/core/pfe-core/decorators/bound.ts +++ b/core/pfe-core/decorators/bound.ts @@ -2,7 +2,9 @@ const configurable = true; /** * Binds a class method to the instance - * + * @param _ + * @param key + * @param descriptor * @example Binding an event listener * ```ts * private mo = new MutationObserver(this.onMutation); diff --git a/core/pfe-core/decorators/cascades.ts b/core/pfe-core/decorators/cascades.ts index f800aa93bf..84134434c3 100644 --- a/core/pfe-core/decorators/cascades.ts +++ b/core/pfe-core/decorators/cascades.ts @@ -4,7 +4,8 @@ import { CascadeController } from '../controllers/cascade-controller.js'; /** * Cascades the decorated attribute to children - * @deprecated: use context, especially via `@patternfly/pfe-core/functions/context.js`; + * @param items + * @deprecated use context, especially via `@patternfly/pfe-core/functions/context.js`; */ export function cascades(...items: string[]): PropertyDecorator { return function(proto: T, key: string & keyof T) { diff --git a/core/pfe-core/decorators/deprecation.ts b/core/pfe-core/decorators/deprecation.ts index 20c5ff7c27..2147701260 100644 --- a/core/pfe-core/decorators/deprecation.ts +++ b/core/pfe-core/decorators/deprecation.ts @@ -9,13 +9,14 @@ export type DeprecationDeclaration = PropertyDeclaration /** * Aliases the decorated field to an existing property, and logs a warning if it is used + * @param options alias is a drop in replacement * @example deprecating an attribute - * ```ts - * @property({ reflect: true, attribute: 'color-palette'}) - * colorPalette: ColorPalette = 'base'; + * ```ts + * @property({ reflect: true, attribute: 'color-palette'}) + * colorPalette: ColorPalette = 'base'; * - * @deprecation('colorPalette') color?: ColorPalette; - * ``` + * @deprecation('colorPalette') color?: ColorPalette; + * ``` */ export function deprecation(options: DeprecationDeclaration) { return function( diff --git a/core/pfe-core/decorators/observed.ts b/core/pfe-core/decorators/observed.ts index 48806b40ce..a290bb3d20 100644 --- a/core/pfe-core/decorators/observed.ts +++ b/core/pfe-core/decorators/observed.ts @@ -12,33 +12,34 @@ import { type TypedFieldDecorator = (proto: T, key: string | keyof T) => void ; +// eslint-disable-next-line jsdoc/require-param /** * Calls a _fooChanged method on the instance when the value changes. * Works on any class field. When using on lit observed properties, * Make sure `@observed` is to the left (i.e. called after) the `@property` * or `@state` decorator. * @example observing a lit property - * ```ts - * @observed @property() foo = 'bar'; + * ```ts + * @observed @property() foo = 'bar'; * - * protected _fooChanged(oldValue?: string, newValue?: string) {} - * ``` + * protected _fooChanged(oldValue?: string, newValue?: string) {} + * ``` * @example using a custom callback - * ```ts - * @observed('_myCallback') size = 'lg'; + * ```ts + * @observed('_myCallback') size = 'lg'; * - * _myCallback(_, size) {...} - * ``` + * _myCallback(_, size) {...} + * ``` * @example using an arrow function - * ```ts - * @observed((oldVal, newVal) => console.log(`Size changed from ${oldVal} to ${newVal}`)) - * ``` + * ```ts + * @observed((oldVal, newVal) => console.log(`Size changed from ${oldVal} to ${newVal}`)) + * ``` */ export function observed(methodName: string): TypedFieldDecorator; export function observed(cb: ChangeCallback): TypedFieldDecorator; export function observed(proto: T, key: string): void; +// eslint-disable-next-line jsdoc/require-jsdoc export function observed(...as: any[]): void | TypedFieldDecorator { - /** @observed('_myCustomChangeCallback') */ if (as.length === 1) { const [methodNameOrCallback] = as; return function(proto, key) { @@ -54,6 +55,12 @@ export function observed(...as: any[]): void | TypedF } } +/** + * Creates an observer on a field + * @param proto + * @param key + * @param callbackOrMethod + */ export function observeProperty( proto: T, key: string & keyof T, diff --git a/core/pfe-core/decorators/trace.ts b/core/pfe-core/decorators/trace.ts index e94328ba83..165bd8669a 100644 --- a/core/pfe-core/decorators/trace.ts +++ b/core/pfe-core/decorators/trace.ts @@ -1,4 +1,7 @@ -/** Logs the result of a class method */ +/** + * Logs the result of a class method + * @param tag log tag, prepended to outputs + */ export function trace(tag?: string) { return function(_: unknown, key: string, descriptor: PropertyDescriptor) { const { value: f } = descriptor; diff --git a/core/pfe-core/functions/containsDeep.ts b/core/pfe-core/functions/containsDeep.ts index f339507fa7..9a00f2bd4d 100644 --- a/core/pfe-core/functions/containsDeep.ts +++ b/core/pfe-core/functions/containsDeep.ts @@ -2,6 +2,8 @@ * Whether or not the container contains the node, * and if not, whether the node is contained by any element * slotted in to the container + * @param container haystack + * @param node needle */ export function containsDeep(container: Element, node: Node) { if (container.contains(node)) { diff --git a/core/pfe-core/functions/context.ts b/core/pfe-core/functions/context.ts index baa8a1aeee..f7e8919454 100644 --- a/core/pfe-core/functions/context.ts +++ b/core/pfe-core/functions/context.ts @@ -13,6 +13,7 @@ function makeContextRoot() { * In order to prevent late-upgrading-context-consumers from 'missing' * their rightful context providers, we must set up a `ContextRoot` on the body. * Always use this function when creating contexts that are shared with child elements. + * @param args createContext args */ export function createContextWithRoot(...args: Parameters) { root ??= makeContextRoot(); diff --git a/docs/_plugins/cem-render.cjs b/docs/_plugins/cem-render.cjs index d2931c00ea..5042e659a7 100644 --- a/docs/_plugins/cem-render.cjs +++ b/docs/_plugins/cem-render.cjs @@ -1,11 +1,20 @@ -/** quick and dirty dedent, also provides in-editor syntax highlighting */ +/** + * quick and dirty dedent, also provides in-editor syntax highlighting + * @param {string[]} args + */ const html = (...args) => String.raw(...args) .split('\n') .map(x => x.replace(/^ {6}/, '')) .join('\n'); -/** @typedef {import('@patternfly/pfe-tools/11ty/DocsPage').DocsPage} DocsPage */ +/** + * @import { UserConfig } from '@11ty/eleventy' + */ + +/** + * @param {UserConfig} eleventyConfig + */ module.exports = function(eleventyConfig) { eleventyConfig.addPairedShortcode('renderCodeDocs', function renderCodeDocs(content, kwargs = {}) { @@ -42,14 +51,7 @@ function renderBand(content, { level, header = '' } = {}) { `; } -/** - * docs pages contain a #styling-hooks anchor as back compat for older versions of the page - * to prevent this id from rendering more than once, we track the number of times each page - * renders css custom properties. - */ -const cssStylingHookIdTracker = new WeakSet(); - -/** @param {import('@11ty/eleventy').UserConfig} eleventyConfig */ +/** @param {UserConfig} eleventyConfig */ module.exports = function(eleventyConfig) { eleventyConfig.addFilter('innerMD', innerMD); eleventyConfig.addFilter('mdHeading', mdHeading); @@ -74,7 +76,6 @@ module.exports = function(eleventyConfig) { }; class Renderers { - /** @type{WeakMap} */ static renderers = new WeakMap(); static forPage(page) { return new Renderers(page); @@ -88,7 +89,6 @@ class Renderers { * NB: since the data for this shortcode is no a POJO, * but a DocsPage instance, 11ty assigns it to this.ctx._ * @see https://github.com/11ty/eleventy/blob/bf7c0c0cce1b2cb01561f57fdd33db001df4cb7e/src/Plugins/RenderPlugin.js#L89-L93 - * @type {DocsPage} */ this.docsPage = page.ctx._; this.manifest = this.docsPage.manifest; @@ -104,7 +104,10 @@ class Renderers { } } - /** Render the overview of a component page */ + /** + * Render the overview of a component page + * @param {string} content + */ renderOverview(content) { return html`
@@ -124,7 +127,13 @@ class Renderers {
`; } - /** Render the list of element attributes */ + /** + * Render the list of element attributes + * @param {string} content inner md content + * @param {object} kwargs + * @param {string} kwargs.header + * @param {number} kwargs.level + */ renderAttributes(content, { header = 'Attributes', level = 2, ...kwargs } = {}) { const _attrs = this.manifest.getAttributes(this.packageTagName(kwargs)) ?? []; const deprecated = _attrs.filter(x => x.deprecated); @@ -169,7 +178,13 @@ class Renderers { `; } - /** Render the list of element DOM properties */ + /** + * Render the list of element DOM properties + * @param {string} content inner md content + * @param {object} kwargs + * @param {string} kwargs.header + * @param {number} kwargs.level + */ renderProperties(content, { header = 'DOM Properties', level = 2, ...kwargs } = {}) { const allProperties = this.manifest.getProperties(this.packageTagName(kwargs)) ?? []; const deprecated = allProperties.filter(x => x.deprecated); @@ -211,7 +226,13 @@ class Renderers { `; } - /** Render a table of element CSS Custom Properties */ + /** + * Render a table of element CSS Custom Properties + * @param {string} content inner md content + * @param {object} kwargs + * @param {string} kwargs.header + * @param {number} kwargs.level + */ renderCssCustomProperties(content, { header = 'CSS Custom Properties', level = 2, @@ -270,7 +291,13 @@ class Renderers { `; } - /** Render the list of element CSS Shadow Parts */ + /** + * Render the list of element CSS Shadow Parts + * @param {string} content inner md content + * @param {object} kwargs + * @param {string} kwargs.header + * @param {number} kwargs.level + */ renderCssParts(content, { header = 'CSS Shadow Parts', level = 2, ...kwargs } = {}) { const allParts = this.manifest.getCssParts(this.packageTagName(kwargs)) ?? []; const parts = allParts.filter(x => !x.deprecated); @@ -297,7 +324,13 @@ class Renderers { `; } - /** Render the list of events for the element */ + /** + * Render the list of events for the element + * @param {string} content inner md content + * @param {object} kwargs + * @param {string} kwargs.header + * @param {number} kwargs.level + */ renderEvents(content, { header = 'Events', level = 2, ...kwargs } = {}) { const _events = this.manifest.getEvents(this.packageTagName(kwargs)) ?? []; const deprecated = _events.filter(x => x.deprecated); @@ -330,7 +363,14 @@ class Renderers { `; } - /** Render the installation instructions for the element */ + /** + * Render the installation instructions for the element + * @param {string} content inner md content + * @param {object} kwargs + * @param {string} kwargs.header + * @param {number} kwargs.level + * @param {string} kwargs.tagName + */ renderInstallation(content, { header = 'Installation', level = 2, @@ -338,7 +378,7 @@ class Renderers { } = {}) { return html`
-

Installation

+ ${header} We recommend loading elements via a CDN such as [JSPM][inst-jspm] and using an import map to manage your dependencies. @@ -369,7 +409,13 @@ class Renderers { [inst-bms]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules`; } - /** Render the list of element methods */ + /** + * Render the list of element methods + * @param {string} content inner md content + * @param {object} kwargs + * @param {string} kwargs.header + * @param {number} kwargs.level + */ renderMethods(content, { header = 'Methods', level = 2, ...kwargs } = {}) { const allMethods = this.manifest.getMethods(this.packageTagName(kwargs)) ?? []; const deprecated = allMethods.filter(x => x.deprecated); @@ -397,7 +443,13 @@ class Renderers {
`; } - /** Render the list of the element's slots */ + /** + * Render the list of the element's slots + * @param {string} content inner md content + * @param {object} kwargs + * @param {string} kwargs.header + * @param {number} kwargs.level + */ renderSlots(content, { header = 'Slots', level = 2, ...kwargs } = {}) { const allSlots = this.docsPage.manifest.getSlots(this.packageTagName(kwargs)) ?? []; const slots = allSlots.filter(x => !x.deprecated); diff --git a/docs/_plugins/pfe-assets.cjs b/docs/_plugins/pfe-assets.cjs index d920fdde4c..240eee6b01 100644 --- a/docs/_plugins/pfe-assets.cjs +++ b/docs/_plugins/pfe-assets.cjs @@ -1,11 +1,6 @@ const fs = require('fs'); const path = require('path'); -/** - * @typedef {object} EleventyTransformContext - * @property {string} outputPath path this file will be written to - */ - /** * Generate a map of files per package which should be copied to the site dir * @param {object} [options] @@ -55,7 +50,7 @@ const DEMO_PATHS_RE = /** * Replace paths in demo files from the dev SPA's format to 11ty's format - * @this {EleventyTransformContext} + * @param {string} content demo file */ function demoPaths(content) { if (this.outputPath.match(/(components|core|tools)\/.*\/demo\/index\.html$/)) { diff --git a/elements/pf-accordion/test/pf-accordion.spec.ts b/elements/pf-accordion/test/pf-accordion.spec.ts index 032878cf7a..f5fb3a215e 100644 --- a/elements/pf-accordion/test/pf-accordion.spec.ts +++ b/elements/pf-accordion/test/pf-accordion.spec.ts @@ -1011,7 +1011,6 @@ describe('', function() { describe('with nested pf-accordion', function() { let topLevelHeaderOne: PfAccordionHeader; let topLevelHeaderTwo: PfAccordionHeader; - let topLevelHeaderThree: PfAccordionHeader; let topLevelPanelOne: PfAccordionPanel; let topLevelPanelTwo: PfAccordionPanel; @@ -1077,7 +1076,6 @@ describe('', function() { `); topLevelHeaderOne = document.getElementById('header-1') as PfAccordionHeader; topLevelHeaderTwo = document.getElementById('header-2') as PfAccordionHeader; - topLevelHeaderThree = document.getElementById('header-3') as PfAccordionHeader; topLevelPanelOne = document.getElementById('panel-1') as PfAccordionPanel; topLevelPanelTwo = document.getElementById('panel-2') as PfAccordionPanel; @@ -1355,7 +1353,6 @@ describe('', function() { describe('with a single expanded header and panel containing a checkbox and a switch', function() { let element: PfAccordion; - let headers: NodeListOf; let panels: NodeListOf; let checkbox: HTMLInputElement; let pfswitch: PfSwitch; @@ -1371,7 +1368,6 @@ describe('', function() { `); - headers = document.querySelectorAll('pf-accordion-header'); panels = document.querySelectorAll('pf-accordion-panel'); checkbox = element.querySelector('input')!; pfswitch = element.querySelector('pf-switch')!; diff --git a/elements/pf-button/demo/block.html b/elements/pf-button/demo/block.html index 55b8fdf1c2..37952652e4 100644 --- a/elements/pf-button/demo/block.html +++ b/elements/pf-button/demo/block.html @@ -6,7 +6,6 @@ import 'element-internals-polyfill'; import '@patternfly/elements/pf-button/pf-button.js'; for (const button of document.querySelectorAll('pf-button')) { - // eslint-disable-next-line no-console button.addEventListener('click', console.log); } diff --git a/elements/pf-button/demo/sizes.html b/elements/pf-button/demo/sizes.html index 42c5fdfd56..8a5bca1070 100644 --- a/elements/pf-button/demo/sizes.html +++ b/elements/pf-button/demo/sizes.html @@ -18,7 +18,6 @@ import 'element-internals-polyfill'; import '@patternfly/elements/pf-button/pf-button.js'; for (const button of document.querySelectorAll('pf-button')) { - // eslint-disable-next-line no-console button.addEventListener('click', console.log); } diff --git a/elements/pf-button/demo/variants.html b/elements/pf-button/demo/variants.html index f216382edf..589b88b0de 100644 --- a/elements/pf-button/demo/variants.html +++ b/elements/pf-button/demo/variants.html @@ -85,7 +85,6 @@

Disabled

import 'element-internals-polyfill'; import '@patternfly/elements/pf-button/pf-button.js'; for (const button of document.querySelectorAll('pf-button')) { - // eslint-disable-next-line no-console button.addEventListener('click', console.log); } diff --git a/elements/pf-chip/pf-chip-group.ts b/elements/pf-chip/pf-chip-group.ts index 17377b82cb..d64a42e895 100644 --- a/elements/pf-chip/pf-chip-group.ts +++ b/elements/pf-chip/pf-chip-group.ts @@ -197,6 +197,7 @@ export class PfChipGroup extends LitElement { /** * handles a chip's `chip-remove` event + * @param event remove event */ async #onChipRemoved(event: Event) { if (event instanceof PfChipRemoveEvent) { @@ -216,6 +217,7 @@ export class PfChipGroup extends LitElement { /** * handles overflow chip's click event + * @param event click event */ async #onMoreClick(event: Event) { event.stopPropagation(); @@ -259,6 +261,7 @@ export class PfChipGroup extends LitElement { /** * Activates the specified chip and sets focus on it + * @param chip pf-chip element */ focusOnChip(chip: HTMLElement) { this.#tabindex.setActiveItem(chip); diff --git a/elements/pf-dropdown/pf-dropdown-item.ts b/elements/pf-dropdown/pf-dropdown-item.ts index b86fb5ea25..10769e2d31 100644 --- a/elements/pf-dropdown/pf-dropdown-item.ts +++ b/elements/pf-dropdown/pf-dropdown-item.ts @@ -5,8 +5,6 @@ import { classMap } from 'lit/directives/class-map.js'; import { query } from 'lit/decorators/query.js'; import { consume } from '@lit/context'; -import { InternalsController } from '@patternfly/pfe-core/controllers/internals-controller.js'; - import { context, type PfDropdownContext } from './context.js'; import styles from './pf-dropdown-item.css'; diff --git a/elements/pf-dropdown/pf-dropdown-menu.ts b/elements/pf-dropdown/pf-dropdown-menu.ts index a492a34267..0ca12e5226 100644 --- a/elements/pf-dropdown/pf-dropdown-menu.ts +++ b/elements/pf-dropdown/pf-dropdown-menu.ts @@ -104,6 +104,7 @@ export class PfDropdownMenu extends LitElement { /** * handles focusing on an option: * updates roving tabindex and active descendant + * @param event the focus event */ #onMenuitemFocusin(event: FocusEvent) { if (this.ctx?.disabled) { @@ -119,6 +120,7 @@ export class PfDropdownMenu extends LitElement { * handles clicking on a menuitem: * which selects an item by default * or toggles selection if multiselectable + * @param event the click event */ #onMenuitemClick(event: MouseEvent) { if (this.ctx?.disabled || isDisabledItemClick(event)) { diff --git a/elements/pf-icon/pf-icon.ts b/elements/pf-icon/pf-icon.ts index 64943bc3c5..077d18f4bb 100644 --- a/elements/pf-icon/pf-icon.ts +++ b/elements/pf-icon/pf-icon.ts @@ -1,4 +1,4 @@ -import { LitElement, html, isServer, type PropertyValues } from 'lit'; +import { LitElement, html, type PropertyValues } from 'lit'; import { customElement } from 'lit/decorators/custom-element.js'; import { property } from 'lit/decorators/property.js'; import { state } from 'lit/decorators/state.js'; @@ -12,7 +12,10 @@ type Renderable = unknown; export type IconResolverFunction = (set: string, icon: string) => Renderable | Promise; -/** requestIdleCallback when available, requestAnimationFrame when not */ +/** + * requestIdleCallback when available, requestAnimationFrame when not + * @param f callback + */ const ric: typeof globalThis.requestIdleCallback = globalThis.requestIdleCallback ?? globalThis.requestAnimationFrame diff --git a/elements/pf-icon/test/pf-icon.spec.ts b/elements/pf-icon/test/pf-icon.spec.ts index fd1f2c46f2..4d64595160 100644 --- a/elements/pf-icon/test/pf-icon.spec.ts +++ b/elements/pf-icon/test/pf-icon.spec.ts @@ -16,7 +16,7 @@ import api from './rh-icon-api.js'; import atom from './rh-icon-atom.js'; // @ts-ignore: don't want to include these import bike from './rh-icon-bike.js'; -import { a11ySnapshot } from '@patternfly/pfe-tools/test/a11y-snapshot.js'; + /* eslint-enable @typescript-eslint/ban-ts-comment */ const TEST_ICONS = { aed, api, atom, bike }; diff --git a/elements/pf-modal/pf-modal.ts b/elements/pf-modal/pf-modal.ts index 866a9c95ef..c2c7a05096 100644 --- a/elements/pf-modal/pf-modal.ts +++ b/elements/pf-modal/pf-modal.ts @@ -307,6 +307,7 @@ export class PfModal extends LitElement implements HTMLDialogElement { * ```js * modal.close(); * ``` + * @param returnValue dialog return value */ @bound close(returnValue?: string) { if (typeof returnValue === 'string') { diff --git a/elements/pf-popover/pf-popover.ts b/elements/pf-popover/pf-popover.ts index 0a1b22684d..7bab385f55 100644 --- a/elements/pf-popover/pf-popover.ts +++ b/elements/pf-popover/pf-popover.ts @@ -459,6 +459,7 @@ export class PfPopover extends LitElement { /** * Removes event listeners from the old trigger element and attaches * them to the new trigger element. + * @param changed changed props */ override willUpdate(changed: PropertyValues) { if (changed.has('trigger')) { diff --git a/elements/pf-popover/test/pf-popover.spec.ts b/elements/pf-popover/test/pf-popover.spec.ts index 72ef5614a7..bd44cd1722 100644 --- a/elements/pf-popover/test/pf-popover.spec.ts +++ b/elements/pf-popover/test/pf-popover.spec.ts @@ -1,5 +1,5 @@ import { expect, html, fixture, fixtureCleanup, nextFrame } from '@open-wc/testing'; -import { a11ySnapshot, type A11yTreeSnapshot } from '@patternfly/pfe-tools/test/a11y-snapshot.js'; +import { a11ySnapshot } from '@patternfly/pfe-tools/test/a11y-snapshot.js'; import { clickElementAtCenter } from '@patternfly/pfe-tools/test/utils.js'; import { sendKeys, resetMouse } from '@web/test-runner-commands'; import { PfPopover } from '@patternfly/elements/pf-popover/pf-popover.js'; @@ -29,18 +29,6 @@ describe('', function() { await expect(element).to.be.accessible(); } - /** - * Assert that the accessibility tree reports the expected snapshot - * e.g. for a closed popover, does not announce popover child content - * e.g. for an opened popover, it does announce popover child content - * If the expected children snapshot is undefined, then assistive technology - * reports nothing at all, e.g. a popover element with no attrs and no children - */ - async function expectA11ySnapshot(expected: A11yTreeSnapshot = { role: 'WebArea', name: '' }) { - const snapshot = await a11ySnapshot(); - expect(snapshot).to.deep.equal(expected); - } - function resetElement() { document.querySelectorAll('pf-popover').forEach(e => e.remove()); // @ts-expect-error: resetting test state, so we don't mind the ts error. diff --git a/elements/pf-progress-stepper/pf-progress-stepper.ts b/elements/pf-progress-stepper/pf-progress-stepper.ts index 8333d3a072..bf993caf9b 100644 --- a/elements/pf-progress-stepper/pf-progress-stepper.ts +++ b/elements/pf-progress-stepper/pf-progress-stepper.ts @@ -1,7 +1,6 @@ import { LitElement, html, type PropertyValues } from 'lit'; import { customElement } from 'lit/decorators/custom-element.js'; import { property } from 'lit/decorators/property.js'; -import { observed } from '@patternfly/pfe-core/decorators/observed.js'; import style from './pf-progress-stepper.css'; diff --git a/elements/pf-select/pf-select.ts b/elements/pf-select/pf-select.ts index a770547db1..1ec80f585e 100644 --- a/elements/pf-select/pf-select.ts +++ b/elements/pf-select/pf-select.ts @@ -1,5 +1,3 @@ -import type { PfChipRemoveEvent } from '@patternfly/elements/pf-chip/pf-chip.js'; - import { LitElement, html, isServer, type PropertyValues } from 'lit'; import { customElement } from 'lit/decorators/custom-element.js'; import { property } from 'lit/decorators/property.js'; @@ -437,9 +435,11 @@ export class PfSelect extends LitElement { /** * handles chip's remove button clicking - * @param opt chip text to be removed from values + * @param event remove event + * @param opt pf-option */ - #onChipRemove(opt: PfOption, event: PfChipRemoveEvent) { + #onChipRemove(opt: PfOption, event: Event) { + event; opt; // if (event.chip) { // opt.selected = false; // this._input?.focus(); diff --git a/elements/pf-tooltip/pf-tooltip.ts b/elements/pf-tooltip/pf-tooltip.ts index 773b3e1719..5d95cad135 100644 --- a/elements/pf-tooltip/pf-tooltip.ts +++ b/elements/pf-tooltip/pf-tooltip.ts @@ -162,6 +162,7 @@ export class PfTooltip extends LitElement { /** * Removes event listeners from the old trigger element and attaches * them to the new trigger element. + * @param changed changed properties */ override willUpdate(changed: PropertyValues) { if (changed.has('trigger')) { diff --git a/playwright.config.ts b/playwright.config.ts index 887e46e358..8e59633326 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -1,4 +1,4 @@ -import { defineConfig, type ReporterDescription } from '@playwright/test'; +import { defineConfig } from '@playwright/test'; export default defineConfig({ testMatch: 'elements/**/*.e2e.ts', diff --git a/scripts/bundle-release.cjs b/scripts/bundle-release.cjs index 70c41fbbc1..0addf4be33 100644 --- a/scripts/bundle-release.cjs +++ b/scripts/bundle-release.cjs @@ -1,13 +1,5 @@ // @ts-check -/** - * @typedef {object} API - * @property {import('@actions/core')} core - * @property {import('@actions/exec')} exec - * @property {import('@actions/glob')} glob - * @property {import('@octokit/rest').Octokit} github - */ - /** @param {number} ms */ const sleep = ms => new Promise(r => setTimeout(r, ms)); @@ -47,7 +39,7 @@ async function execCommand(exec, command) { * @param {(...args: any[]) => T} fn async function to be backed off * @param {number} retries current count of retries * @param {number} max Max number of retries - * @return {Promise} + * @returns {Promise} */ async function backoff(fn, retries = 0, max = 10) { try { @@ -66,9 +58,9 @@ async function backoff(fn, retries = 0, max = 10) { /** * @param {object} params - * @param {API} params.api + * @param {*} params.api * @param {string} params.workspace - * @return string filename + * @returns {Promise} filename */ async function getBundle({ api, workspace }) { const { basename } = require('path'); @@ -95,7 +87,6 @@ async function getBundle({ api, workspace }) { } } -/** @typedef {Awaited>['data']} Release */ /** * @param {object} params @@ -127,7 +118,6 @@ async function uploadAssetOverwriting({ api, owner, repo, tag, workspace, releas repo, release_id: release.id, name, - // @ts-expect-error: seems to work tho data, }); } @@ -148,7 +138,6 @@ async function uploadAssetOverwriting({ api, owner, repo, tag, workspace, releas module.exports = async function bundle({ tags = '', workspace, ...api }) { await execCommand(api.exec, 'git config advice.detachedHead false'); - /** @type {API} */ api; const tagsList = tags.split(',').map(x => x.trim()); diff --git a/scripts/bundle.js b/scripts/bundle.js index d44f1f51e8..f83f7fcede 100755 --- a/scripts/bundle.js +++ b/scripts/bundle.js @@ -17,6 +17,10 @@ const entryPoints = const contents = entryPoints.map(x => `export * from './${x}';`).join('\n'); +/** + * @param {object} options + * @param {object} options.outfile file path to bundle to + */ export async function bundle({ outfile = 'elements/pfe.min.js' } = {}) { await build({ stdin: { diff --git a/scripts/format-commitlint-messages.js b/scripts/format-commitlint-messages.js index 4638473f35..fce9a78675 100644 --- a/scripts/format-commitlint-messages.js +++ b/scripts/format-commitlint-messages.js @@ -1,3 +1,9 @@ +/** + * formats commitlint action results + * @param {object} opts + * @param {*[]} opts.results + * @param {boolean} opts.titleGood is the PR title acceptable + */ export function format({ results, titleGood }) { try { const totalErrors = results.reduce((a, r) => a + r.errors.length, 0); diff --git a/scripts/format-lighthouse.cjs b/scripts/format-lighthouse.cjs index 5abb3a618d..0aad1955ce 100644 --- a/scripts/format-lighthouse.cjs +++ b/scripts/format-lighthouse.cjs @@ -11,7 +11,6 @@ function titleCase(str) { module.exports = ({ links, assertionResults }) => { // pretty sure that's a false negative - // eslint-disable-next-line unicorn/prefer-object-from-entries const failures = assertionResults.reduce((acc, result) => { const forUrl = acc[result.url] || {}; diff --git a/tools/create-element/generator/element.ts b/tools/create-element/generator/element.ts index 11d2942d49..c7dbd6d435 100644 --- a/tools/create-element/generator/element.ts +++ b/tools/create-element/generator/element.ts @@ -98,7 +98,11 @@ const getInterpolations = }; }); -/** e.g. /Users/alj/Developer/jazz-elements/elements/pf-jazz-hands/pf-jazz-hands.ts */ +/** + * e.g. /home/alj/Developer/jazz-elements/elements/pf-jazz-hands/pf-jazz-hands.ts + * @param key file key e.g. component + * @param options element generator options + */ const getOutputFilePath = (key: FileKey, options: GenerateElementOptions): string => join(getComponentAbsPath(options), getFilePathsRelativeToPackageDir(options)[key]); @@ -162,6 +166,7 @@ export class PackageJSONError extends Error {} /** * Generate an Element + * @param options element generator options */ export async function generateElement(options: GenerateElementOptions): Promise { // eslint-disable-next-line no-console diff --git a/tools/create-element/generator/files.ts b/tools/create-element/generator/files.ts index 381211394e..13626ce18f 100644 --- a/tools/create-element/generator/files.ts +++ b/tools/create-element/generator/files.ts @@ -2,6 +2,9 @@ import { mkdir, readFile, stat, writeFile } from 'fs/promises'; export { readFile, writeFile }; +/** + * @param [string] prop name + */ export function getInterpolationRegExp(string?: string): RegExp { if (typeof string === 'string') { return new RegExp(`<%= ${string} %>`, 'g'); @@ -10,6 +13,10 @@ export function getInterpolationRegExp(string?: string): RegExp { } } +/** + * @param template ejs-like template + * @param interpolations record of keywords to replace. + */ export function processTemplate(template: string, interpolations: Record): string { let partial = template; @@ -21,7 +28,10 @@ export function processTemplate(template: string, interpolations: Record { try { return !!(await stat(path)); @@ -30,11 +40,17 @@ export async function exists(path: string): Promise { } } -/** $ mkdir -p path */ +/** + * $ mkdir -p path + * @param path dir to mk, p + */ export async function mkdirp(path: string): Promise { await mkdir(path, { recursive: true }); } +/** + * @param path json file path + */ export async function readJson(path: string): Promise { return readFile(path, 'utf8').then(x => JSON.parse(x)); } diff --git a/tools/create-element/generator/fp.ts b/tools/create-element/generator/fp.ts index cdae9ada0c..968d894926 100644 --- a/tools/create-element/generator/fp.ts +++ b/tools/create-element/generator/fp.ts @@ -1,4 +1,7 @@ -/** Memoize an oft-called nary function */ +/** + * Memoize an oft-called nary function + * @param fn pure function to memoize + */ export function memoize unknown>(fn: T): T { if (!fn) { throw new Error('Trying to memoize non-function'); diff --git a/tools/create-element/main.ts b/tools/create-element/main.ts index 90db7ebc50..cc3b6664d0 100644 --- a/tools/create-element/main.ts +++ b/tools/create-element/main.ts @@ -69,6 +69,9 @@ function banner() { ${Chalk.bold(Chalk.blue('PatternFly Elements'))}`); } +/** + * @param options the tag and package names, among others + */ export async function promptForElementGeneratorOptions( options?: PromptOptions ): Promise { @@ -97,6 +100,9 @@ async function getDefaultPackageName() { ?? (await readJsonOrVoid(join(process.cwd(), 'package.json')) as PackageJSON)?.name ?? ''; } +/** + * Prompt to generate an element definition + */ export async function main(): Promise { return Promise.resolve( (Yargs(process.argv) as Yargs.Argv) diff --git a/tools/eslint-config/configs/pfe.js b/tools/eslint-config/configs/pfe.js index d68e09ebbb..f0094ed966 100644 --- a/tools/eslint-config/configs/pfe.js +++ b/tools/eslint-config/configs/pfe.js @@ -8,17 +8,41 @@ import stylistic from '@stylistic/eslint-plugin'; import { States } from '../lib.js'; +const definedTags = [ + 'attr', + 'attribute', + 'cssprop', + 'cssproperty', + 'fires', + 'slot', + 'csspart', +]; + export default [ { name: 'eslint/recommended', ...js.configs.recommended }, { name: 'jsdoc/flat/recommended-typescript', - files: ['**/*.ts'], ...jsdoc.configs['flat/recommended-typescript'], + files: ['**/*.ts'], + plugins: { jsdoc }, + rules: { + 'jsdoc/require-jsdoc': [States.WARNING, { publicOnly: true, enableFixer: false }], + 'jsdoc/require-param': [States.WARNING, { enableFixer: true }], + 'jsdoc/require-returns': [States.OFF, { enableFixer: true }], + 'jsdoc/check-tag-names': [States.WARNING, { typed: true, enableFixer: false, definedTags }], + }, }, { name: 'jsdoc/flat/recommended-typescript-flavor', - files: ['**/*.js', '**/*.cjs', '**/*.mjs'], ...jsdoc.configs['flat/recommended-typescript-flavor'], + files: ['**/*.js', '**/*.cjs', '**/*.mjs'], + plugins: { jsdoc }, + rules: { + 'jsdoc/require-jsdoc': [States.WARNING, { publicOnly: true, enableFixer: false }], + 'jsdoc/require-param': [States.WARNING, { enableFixer: true }], + 'jsdoc/require-returns': [States.OFF, { enableFixer: true }], + 'jsdoc/check-tag-names': [States.WARNING, { typed: false, enableFixer: false, definedTags }], + }, }, { name: '@patternfly/elements', diff --git a/tools/netlify-plugin-github-actions/index.js b/tools/netlify-plugin-github-actions/index.js index 6c73238ab9..ff8e2826d0 100644 --- a/tools/netlify-plugin-github-actions/index.js +++ b/tools/netlify-plugin-github-actions/index.js @@ -1,5 +1,12 @@ import { Octokit } from '@octokit/core'; +/** + * netlify plugin which posts a message to the associated github PR thread + * @param {object} opts + * @param {object} opts.netlifyConfig netlify project config + * @param {object} opts.inputs owner, repository, and workflowId + * @param {object} opts.utils octokit utils + */ export async function onSuccess({ netlifyConfig, inputs, utils }) { const { BRANCH: branch, diff --git a/tools/pfe-tools/config.ts b/tools/pfe-tools/config.ts index 15c8101275..9e5aef5be2 100644 --- a/tools/pfe-tools/config.ts +++ b/tools/pfe-tools/config.ts @@ -61,6 +61,10 @@ function tryJson(path: string) { } } +/** + * Get a normalized pfe config for the repo + * @param [rootDir=process.cwd()] repo root + */ export function getPfeConfig(rootDir = process.cwd()): Required { const jsonConfig = tryJson(join(rootDir, '.pfe.config.json')); return { @@ -90,6 +94,8 @@ function getSlugsMap(rootDir: string) { /** * Returns the prefixed custom element name for a given slug + * @param slug element slug e.g. `jazz-hands` for `pf-jazz-hands` + * @param [rootDir=process.cwd()] repo root */ export function deslugify(slug: string, rootDir = process.cwd()): string { const { slugs, config } = getSlugsMap(rootDir); diff --git a/tools/pfe-tools/custom-elements-manifest/config.ts b/tools/pfe-tools/custom-elements-manifest/config.ts index 8739d271b3..d01ee7f4f9 100644 --- a/tools/pfe-tools/custom-elements-manifest/config.ts +++ b/tools/pfe-tools/custom-elements-manifest/config.ts @@ -20,7 +20,8 @@ type Options = Config /** * PFE Default custom-elements-manifest analyzer config - * @deprecated + * @param options plugin options + * @deprecated this config relies on an old version of cem-a, roll your own */ export function pfeCustomElementsManifestConfig(options?: Options): Config { // eslint-disable-next-line no-console diff --git a/tools/pfe-tools/custom-elements-manifest/demos.ts b/tools/pfe-tools/custom-elements-manifest/demos.ts index 303b8e54f0..cffc30f2fa 100644 --- a/tools/pfe-tools/custom-elements-manifest/demos.ts +++ b/tools/pfe-tools/custom-elements-manifest/demos.ts @@ -25,6 +25,7 @@ import slugify from 'slugify'; * Any remaining demos will all be added to the primary element's list, e.g. * `/elements/pf-jazz-hands/demo/accessibility.html` would be associated with * `/elements/pf-jazz-hands/pf-jazz-hands.js` + * @param options pfe config */ export function demosPlugin(options?: PfeConfig): Plugin { const fileOptions = getPfeConfig(options?.rootDir); diff --git a/tools/pfe-tools/custom-elements-manifest/ecma-private-class-members.ts b/tools/pfe-tools/custom-elements-manifest/ecma-private-class-members.ts index c00aa5eb49..6011d847e3 100644 --- a/tools/pfe-tools/custom-elements-manifest/ecma-private-class-members.ts +++ b/tools/pfe-tools/custom-elements-manifest/ecma-private-class-members.ts @@ -1,6 +1,9 @@ import type { CustomElement } from 'custom-elements-manifest/schema'; import type { Plugin } from '@custom-elements-manifest/analyzer'; +/** + * cem plugin to mark ecma #private members as private + */ export function ecmaPrivateClassMembersPlugin(): Plugin { return { name: 'ecma-private-class-members-plugin', diff --git a/tools/pfe-tools/custom-elements-manifest/jsdoc-description-default.ts b/tools/pfe-tools/custom-elements-manifest/jsdoc-description-default.ts index 8a1f6eaa20..6fcdfdf099 100644 --- a/tools/pfe-tools/custom-elements-manifest/jsdoc-description-default.ts +++ b/tools/pfe-tools/custom-elements-manifest/jsdoc-description-default.ts @@ -44,6 +44,11 @@ function deinlineDefault( dedent(existing.description?.replace(DEFAULT_RE, '') ?? ''); } } + +/** + * cem analyzer plugin to add non-standard default inline tag + * @deprecated - replace with [name=default] syntax + */ export function jsdocDescriptionDefaultPlugin(): Plugin { return { name: 'jsdoc-description-default-plugin', diff --git a/tools/pfe-tools/custom-elements-manifest/lib/Manifest.ts b/tools/pfe-tools/custom-elements-manifest/lib/Manifest.ts index 9469001b72..77e6747b25 100644 --- a/tools/pfe-tools/custom-elements-manifest/lib/Manifest.ts +++ b/tools/pfe-tools/custom-elements-manifest/lib/Manifest.ts @@ -217,60 +217,70 @@ export class Manifest { } /** + * @param tagName tag to get attributes for */ getAttributes(tagName: string): undefined | Attribute[] { return this.#tag(tagName)?.attributes; } /** + * @param tagName tag to get css props for */ getCssCustomProperties(tagName: string): undefined | CssCustomProperty[] { return this.#tag(tagName)?.cssCustomProperties; } /** + * @param tagName tag to get css parts for */ getCssParts(tagName: string): undefined | CssPart[] { return this.#tag(tagName)?.cssParts; } /** + * @param tagName tag to get description for */ getDescription(tagName: string): undefined | string { return this.#tag(tagName)?.description; } /** + * @param tagName tag to get events for */ getEvents(tagName: string): undefined | Event[] { return this.#tag(tagName)?.events; } /** + * @param tagName tag to get methods for */ getMethods(tagName: string): undefined | ClassMethod[] { return this.#tag(tagName)?.methods; } /** + * @param tagName tag to get properties for */ getProperties(tagName: string): undefined | ClassField[] { return this.#tag(tagName)?.properties; } /** + * @param tagName tag to get summary for */ getSummary(tagName: string): undefined | string { return this.#tag(tagName)?.summary; } /** + * @param tagName tag to get slots for */ getSlots(tagName: string): undefined | Slot[] { return this.#tag(tagName)?.slots; } /** + * @param tagName tag to get demos for */ getDemos(tagName: string): Demo[] { return this.#tag(tagName)?.demos ?? []; diff --git a/tools/pfe-tools/custom-elements-manifest/lib/get-all-packages.ts b/tools/pfe-tools/custom-elements-manifest/lib/get-all-packages.ts index dabd1071ea..1c32fded97 100644 --- a/tools/pfe-tools/custom-elements-manifest/lib/get-all-packages.ts +++ b/tools/pfe-tools/custom-elements-manifest/lib/get-all-packages.ts @@ -40,6 +40,11 @@ function findPackages(packageSpecs: string[], rootDirectory: string): PackageRec .filter((x): x is PackageRecord => !!x.package?.name); } +/** + * get all the package json manifests in a repo, + * whether a single package repo, or a monorepo. + * @param rootDir path to the root package of the monorepo, or the package + */ export function getAllPackages(rootDir: string): PackageRecord[] { const rootPackagePath = join(rootDir, 'package.json'); const rootPackage = readJsonSync(rootPackagePath); diff --git a/tools/pfe-tools/custom-elements-manifest/version-static-field.ts b/tools/pfe-tools/custom-elements-manifest/version-static-field.ts index 9b4b54e721..e5a2179991 100644 --- a/tools/pfe-tools/custom-elements-manifest/version-static-field.ts +++ b/tools/pfe-tools/custom-elements-manifest/version-static-field.ts @@ -17,6 +17,9 @@ function isVersionStatic(member: ClassMember): member is ClassField { return !!member.static && member.name === 'version'; } +/** + * Add the static `version` field to custom element class declarations + */ export function versionStaticFieldPlugin(): Plugin { return { name: 'version-static-field-plugin', diff --git a/tools/pfe-tools/dev-server/config.ts b/tools/pfe-tools/dev-server/config.ts index 8fbf1efebb..11b3a589f4 100644 --- a/tools/pfe-tools/dev-server/config.ts +++ b/tools/pfe-tools/dev-server/config.ts @@ -62,7 +62,11 @@ function normalizeOptions(options?: PfeDevServerConfigOptions) { return config as Required & { site: Required }; } -/** CORS middleware */ +/** + * CORS middleware + * @param ctx koa context + * @param next middleware + */ function cors(ctx: Context, next: Next) { ctx.set('Access-Control-Allow-Origin', '*'); return next(); @@ -94,6 +98,7 @@ function liveReloadTsChangesMiddleware( /** * Creates a default config for PFE's dev server. + * @param options dev server config */ export function pfeDevServerConfig(options?: PfeDevServerConfigOptions): DevServerConfig { const config = normalizeOptions(options); @@ -157,7 +162,11 @@ export function pfeDevServerConfig(options?: PfeDevServerConfigOptions): DevServ }; } -/** Returns an import map `imports` section containing the entire `@patternfly/icons` collection, pointing to node_modules */ +/** + * Returns an import map `imports` section containing the entire + * `@patternfly/icons` collection, pointing to node_modules + * @param rootUrl repository root + */ export async function getPatternflyIconNodemodulesImports(rootUrl: string) { const files = await readdir(new URL('./node_modules/@patternfly/icons', rootUrl)); const dirs = []; diff --git a/tools/pfe-tools/dev-server/plugins/import-map-generator.ts b/tools/pfe-tools/dev-server/plugins/import-map-generator.ts index 7f51d4d480..58d87dede6 100644 --- a/tools/pfe-tools/dev-server/plugins/import-map-generator.ts +++ b/tools/pfe-tools/dev-server/plugins/import-map-generator.ts @@ -96,6 +96,9 @@ function generatorMiddleware(generator: Generator, options?: Partial): }; } +/** + * @param options plugin options + */ export function importMapGeneratorPlugin(options?: Partial): Plugin { return { name: 'import-map-inject', diff --git a/tools/pfe-tools/environment.ts b/tools/pfe-tools/environment.ts index fc07e43242..086fcfa8d4 100644 --- a/tools/pfe-tools/environment.ts +++ b/tools/pfe-tools/environment.ts @@ -2,6 +2,12 @@ import { readdir, stat } from 'fs/promises'; import { join } from 'path'; +/** + * Generate and write a demo environment file + * this is used to pass filesystem information to the client, + * e.g. the list of directories under `elements/` + * @param [cwd=process.cwd()] cwd + */ export async function makeDemoEnv(cwd = process.cwd()): Promise { const iconsDir = join(cwd, 'node_modules', '@patternfly', 'icons'); const dirContents = await readdir(iconsDir); diff --git a/tools/pfe-tools/react/generate-wrappers.ts b/tools/pfe-tools/react/generate-wrappers.ts index 86ac859847..2f5c4c697d 100644 --- a/tools/pfe-tools/react/generate-wrappers.ts +++ b/tools/pfe-tools/react/generate-wrappers.ts @@ -28,13 +28,20 @@ function isExported(exports: CEM.Export[] | undefined) { }; } -/** Remove a prefix from a class name */ +/** + * Remove a prefix from a class name + * @param className ecmascript class name e.g. PfJazzHands + * @param prefix class name prefix e.g. Pf + */ function getDeprefixedClassName(className: string, prefix: string) { const [fst, ...tail] = className.replace(prefix, ''); return `${fst.toUpperCase()}${tail.join('')}`; } -/** simple function to convert string from dash to camel case */ +/** + * simple function to convert string from dash to camel case + * @param str string to convert to camelcase + */ function camel(str: string): string { return str.toLowerCase().replace(/[^a-zA-Z0-9]+(.)/g, (m, chr) => chr.toUpperCase()); } @@ -78,6 +85,7 @@ const getReactWrapperData = ( reactComponentName, eventsMap, eventsInterface, + elPrefix, tagName, }; }; @@ -152,6 +160,15 @@ async function parseManifest(maybeManifest: unknown): Promise { } } +/** + * Given a custom elements manifest (or a path to its file), + * generate a suite of react wrapper components + * @param customElementsManifestOrPathOrURL manifest object; or string or url path + * @param outDirPathOrURL directory to write wrapper components to + * @param packageName npm package name of the manifest + * @param elPrefix element tag prefix e.g. `pf` + * @param classPrefix e.g. `Pf` + */ export async function generateReactWrappers( customElementsManifestOrPathOrURL: CEM.Package | string | URL, outDirPathOrURL: string | URL, diff --git a/tools/pfe-tools/ssr/ssr.ts b/tools/pfe-tools/ssr/ssr.ts index a9b58de85e..872d52689a 100644 --- a/tools/pfe-tools/ssr/ssr.ts +++ b/tools/pfe-tools/ssr/ssr.ts @@ -3,6 +3,9 @@ import { collectResult } from '@lit-labs/ssr/lib/render-result.js'; import { html } from 'lit'; import { unsafeHTML } from 'lit/directives/unsafe-html.js'; +/** + * @param input html partial + */ export async function ssr(input: string) { return collectResult(render(html`${unsafeHTML(input)}`)); } diff --git a/tools/pfe-tools/test/a11y-snapshot.ts b/tools/pfe-tools/test/a11y-snapshot.ts index bcb625a4b5..7ffbb2df56 100644 --- a/tools/pfe-tools/test/a11y-snapshot.ts +++ b/tools/pfe-tools/test/a11y-snapshot.ts @@ -18,6 +18,9 @@ export interface A11yTreeSnapshot { valuemax?: number; } +/** + * @param payload e.g. { selector: 'pf-select' } + */ export async function a11ySnapshot( payload?: Parameters[0] ): Promise { diff --git a/tools/pfe-tools/test/config.ts b/tools/pfe-tools/test/config.ts index eb19e6fe30..a657ec4919 100644 --- a/tools/pfe-tools/test/config.ts +++ b/tools/pfe-tools/test/config.ts @@ -43,6 +43,9 @@ const exists = async (path: string | URL) => { } }; +/** + * @param opts test runner options + */ export function pfeTestRunnerConfig(opts: PfeTestRunnerConfigOptions): TestRunnerConfig { const { open, ...devServerConfig } = pfeDevServerConfig({ ...opts, loadDemo: false }); @@ -105,7 +108,11 @@ export function pfeTestRunnerConfig(opts: PfeTestRunnerConfigOptions): TestRunne a11ySnapshotPlugin(), ], middleware: [ - /** redirect `.js` to `.ts` when the typescript source exists */ + /** + * redirect `.js` to `.ts` when the typescript source exists + * @param ctx koa context + * @param next next middleware + */ async function(ctx, next) { if (ctx.path.endsWith('.js') && ctx.path.startsWith(`/${elementsDir}/${tagPrefix}-`) diff --git a/tools/pfe-tools/test/get-composed-text.ts b/tools/pfe-tools/test/get-composed-text.ts index b0205457cb..d47bc4f121 100644 --- a/tools/pfe-tools/test/get-composed-text.ts +++ b/tools/pfe-tools/test/get-composed-text.ts @@ -1,6 +1,7 @@ /** * Gets the composed text content of an element via the Selection API * WARNING: this is not reliable, should be improved with a treewalker + * @param node node to get text */ export function getComposedText(node: Node) { const range = new Range(); diff --git a/tools/pfe-tools/test/hex-to-rgb.ts b/tools/pfe-tools/test/hex-to-rgb.ts index d77d755aa7..cfc292c192 100644 --- a/tools/pfe-tools/test/hex-to-rgb.ts +++ b/tools/pfe-tools/test/hex-to-rgb.ts @@ -1,6 +1,9 @@ type RGBTuple = [R: number, G: number, B: number, A?: number]; -/** Converts a hex value to RGBA */ +/** + * Converts a hex value to RGBA + * @param hex css hex value e.g. #c0f3f300 + */ export const hexToRgb = (hex: string): RGBTuple => { const [, r, g, b, a] = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})?/.exec(hex) ?? []; const NOTHING = Symbol(); @@ -13,7 +16,11 @@ export const hexToRgb = (hex: string): RGBTuple => { return values.filter(x => x !== NOTHING) as RGBTuple; }; -// Gets the rgba value from an element +/** + * Gets the rgba value from an element's css property + * @param el element to query + * @param prop css property on the element + */ export const getColor = (el: Element, prop: string): RGBTuple => { const [, r, g, b] = (getComputedStyle(el, null) .getPropertyValue(prop) diff --git a/tools/pfe-tools/test/playwright/PfeDemoPage.ts b/tools/pfe-tools/test/playwright/PfeDemoPage.ts index b69ec08f9c..600367730b 100644 --- a/tools/pfe-tools/test/playwright/PfeDemoPage.ts +++ b/tools/pfe-tools/test/playwright/PfeDemoPage.ts @@ -45,20 +45,31 @@ export class PfeDemoPage { await this.page.waitForTimeout(100); } - /** Focus the first instance of the element, or a given selector, then wait for the element's updateComplete */ + /** + * Focus the first instance of the element, or a given selector, + * then wait for the element's updateComplete + * @param [selector=this.tagName] + */ async focus(selector = this.tagName) { await this.page.$eval(selector, el => el.focus()); await this.updateComplete(selector); } - /** Click the first instance of the element, or a given selector, then wait for the element's updateComplete */ + /** + * Click the first instance of the element, or a given selector, + * then wait for the element's updateComplete + * @param [selector=this.tagName] + */ async click(selector = this.tagName) { await this.page.$eval(selector, (el: HTMLElement) => el.click()); await this.updateComplete(selector); } - /** Wait for the element, or a given selector, to update */ - async updateComplete(selector: string | null = this.tagName) { + /** + * Wait for the element, or a given selector, to update + * @param [selector=this.tagName] + */ + async updateComplete(selector = this.tagName) { await this.page.waitForLoadState('domcontentloaded'); await this.page.waitForLoadState('networkidle'); if (selector) { @@ -71,7 +82,10 @@ export class PfeDemoPage { } } - /** Take a snapshot and save it to disk */ + /** + * Take a snapshot and save it to disk + * @param name optional snapshot name + */ async snapshot(name?: string) { const snapshotName = `${this.tagName}${name ? `-${name}` : ''}`; expect(await this.page.screenshot({ fullPage: true })).toMatchSnapshot(`${snapshotName}.png`); diff --git a/tools/pfe-tools/test/render-to-string.ts b/tools/pfe-tools/test/render-to-string.ts index 451a09e68a..46d43a9e68 100644 --- a/tools/pfe-tools/test/render-to-string.ts +++ b/tools/pfe-tools/test/render-to-string.ts @@ -1,6 +1,10 @@ import type { TemplateResult } from 'lit'; import { render } from 'lit'; +/** + * Returns a string representing the innerHTML of the container this template is rendered to + * @param tpl lit-html template + */ export function renderToString(tpl: TemplateResult): string { const frag = new DocumentFragment(); frag.append(document.createElement('div')); diff --git a/tools/pfe-tools/test/utils.ts b/tools/pfe-tools/test/utils.ts index 8a7e654f18..87478e5b46 100644 --- a/tools/pfe-tools/test/utils.ts +++ b/tools/pfe-tools/test/utils.ts @@ -3,6 +3,10 @@ import type { ReactiveElement } from 'lit'; export type Position = [x: number, y: number]; +/** + * Get the center coords of an element. + * @param element get the center of this element's bounding box + */ export function getElementCenterPosition(element: Element): Position { const { x, y, width, height } = element.getBoundingClientRect(); @@ -14,6 +18,7 @@ export function getElementCenterPosition(element: Element): Position { /** * Click an element at approximate center, using playwright's sendMouse command + * @param element to click at it's center */ export async function clickElementAtCenter(element: Element): Promise { const position = getElementCenterPosition(element); @@ -21,7 +26,10 @@ export async function clickElementAtCenter(element: Element): Promise { } /** - * Click an element at an offset from it's top-left corner, using playwright's sendMouse command + * Click an element at an offset from it's top-left corner, + * using playwright's sendMouse command + * @param element to click + * @param relativeOffset x,y coords tuple */ export async function clickElementAtOffset( element: Element, @@ -47,6 +55,7 @@ export async function clickElementAtOffset( /** * Waits for an element to completely finish updating, or throws after 100 attempts * Will also throw if the element doesn't have an `updateComplete` promise + * @param element to wait on */ export async function allUpdates(element: ReactiveElement) { if (!(element.updateComplete instanceof Promise)) { diff --git a/tools/pfe-tools/typescript/transformers/css-imports.cjs b/tools/pfe-tools/typescript/transformers/css-imports.cjs index 61414c18f7..a4b8fa4ebc 100644 --- a/tools/pfe-tools/typescript/transformers/css-imports.cjs +++ b/tools/pfe-tools/typescript/transformers/css-imports.cjs @@ -45,7 +45,7 @@ function createLitCssImportStatement(ctx, sourceFile) { /** * @param {ts.CoreTransformationContext} ctx - * @param {ts.SourceFile} sourceFile + * @param {ts.SourceFile} stylesheet source file * @param {string} [name] */ function createLitCssTaggedTemplateLiteral(ctx, stylesheet, name) { @@ -198,13 +198,16 @@ module.exports = function(program, { return sourceFile => { const children = sourceFile.getChildren(); + + // eslint-disable-next-line + /** @type {ts.ImportDeclaration} */ const litImportBindings = - (children.find(/** @returns {x is ts.ImportDeclaration} */x => + (children.find(x => !ts.isTypeOnlyImportOrExportDeclaration(x) - && !ts.isNamespaceImport(x) - && ts.isImportDeclaration(x) - && x.moduleSpecifier.getText() === 'lit' - && !!x.importClause?.namedBindings + && !ts.isNamespaceImport(x) + && ts.isImportDeclaration(x) + && x.moduleSpecifier.getText() === 'lit' + && x.importClause?.namedBindings ))?.importClause?.namedBindings; const hasStyleImports = children.find(x => From 40b3403e603c394e43d297dfcca2b50088d4786a Mon Sep 17 00:00:00 2001 From: Benny Powers Date: Sun, 7 Jul 2024 16:03:15 +0300 Subject: [PATCH 2/4] chore: update typescript enable `isolatedDeclarations`, which makes our dx a bit worse but improves downstream performance --- .changeset/wide-guests-speak.md | 4 + @types/colorjs.io/index.d.ts | 8 - .../controllers/cascade-controller.ts | 19 +- .../controllers/css-variable-controller.ts | 4 +- .../controllers/floating-dom-controller.ts | 12 +- .../controllers/internals-controller.ts | 22 +- .../controllers/light-dom-controller.ts | 10 +- .../controllers/listbox-controller.ts | 20 +- core/pfe-core/controllers/logger.ts | 26 +- .../controllers/overflow-controller.ts | 12 +- core/pfe-core/controllers/perf-controller.ts | 4 +- .../property-observer-controller.ts | 8 +- .../controllers/roving-tabindex-controller.ts | 17 +- .../controllers/scroll-spy-controller.ts | 10 +- core/pfe-core/controllers/slot-controller.ts | 11 +- .../controllers/tabs-aria-controller.ts | 4 +- .../controllers/timestamp-controller.ts | 10 +- core/pfe-core/core.ts | 4 +- core/pfe-core/decorators/deprecation.ts | 6 +- core/pfe-core/decorators/initializer.ts | 2 +- core/pfe-core/decorators/observed.ts | 2 +- core/pfe-core/decorators/time.ts | 6 +- core/pfe-core/decorators/trace.ts | 6 +- core/pfe-core/functions/containsDeep.ts | 5 +- core/pfe-core/functions/context.ts | 10 +- core/pfe-core/functions/debounce.ts | 2 +- elements/pf-accordion/pf-accordion-header.ts | 10 +- elements/pf-accordion/pf-accordion-panel.ts | 8 +- elements/pf-accordion/pf-accordion.ts | 34 +- elements/pf-avatar/pf-avatar.ts | 6 +- elements/pf-back-to-top/pf-back-to-top.ts | 6 +- .../pf-background-image.ts | 6 +- elements/pf-badge/pf-badge.ts | 6 +- elements/pf-banner/pf-banner.ts | 8 +- elements/pf-button/pf-button.ts | 8 +- elements/pf-card/pf-card.ts | 6 +- elements/pf-chip/pf-chip-group.ts | 16 +- elements/pf-chip/pf-chip.ts | 8 +- .../pf-clipboard-copy/pf-clipboard-copy.ts | 12 +- elements/pf-code-block/pf-code-block.ts | 6 +- elements/pf-dropdown/context.ts | 5 +- elements/pf-dropdown/pf-dropdown-group.ts | 8 +- elements/pf-dropdown/pf-dropdown-item.ts | 8 +- elements/pf-dropdown/pf-dropdown-menu.ts | 14 +- elements/pf-dropdown/pf-dropdown.ts | 20 +- elements/pf-icon/pf-icon.ts | 20 +- elements/pf-jump-links/pf-jump-links-item.ts | 23 +- elements/pf-jump-links/pf-jump-links-list.ts | 6 +- elements/pf-jump-links/pf-jump-links.ts | 12 +- elements/pf-label/pf-label.ts | 8 +- elements/pf-modal/pf-modal.ts | 28 +- elements/pf-panel/pf-panel.ts | 6 +- elements/pf-popover/pf-popover.ts | 44 +- .../pf-progress-stepper/pf-progress-step.ts | 8 +- .../pf-progress-stepper.ts | 10 +- elements/pf-progress/pf-progress.ts | 8 +- elements/pf-select/pf-option-group.ts | 6 +- elements/pf-select/pf-option.ts | 12 +- elements/pf-select/pf-select.ts | 21 +- elements/pf-spinner/pf-spinner.ts | 6 +- elements/pf-switch/pf-switch.ts | 10 +- elements/pf-table/pf-caption.ts | 6 +- elements/pf-table/pf-table.ts | 10 +- elements/pf-table/pf-tbody.ts | 6 +- elements/pf-table/pf-td.ts | 6 +- elements/pf-table/pf-th.ts | 10 +- elements/pf-table/pf-thead.ts | 8 +- elements/pf-table/pf-tr.ts | 6 +- elements/pf-tabs/context.ts | 4 +- elements/pf-tabs/pf-tab-panel.ts | 10 +- elements/pf-tabs/pf-tab.ts | 10 +- elements/pf-tabs/pf-tabs.ts | 10 +- elements/pf-text-area/pf-text-area.ts | 18 +- elements/pf-text-input/pf-text-input.ts | 20 +- elements/pf-tile/pf-tile.ts | 6 +- elements/pf-timestamp/pf-timestamp.ts | 16 +- elements/pf-tooltip/pf-tooltip.ts | 14 +- package-lock.json | 448 +++++++++++------- package.json | 1 + tools/eslint-config/configs/tests.js | 2 + tools/eslint-config/eslint.config.js | 2 +- tools/eslint-config/package.json | 6 +- tools/pfe-tools/config.ts | 7 +- .../custom-elements-manifest/lib/Manifest.ts | 11 +- tools/pfe-tools/dev-server/config.ts | 4 +- tools/pfe-tools/dev-server/demo.ts | 16 +- .../dev-server/plugins/dev-server-router.ts | 4 +- .../plugins/dev-server-templates.ts | 2 +- tools/pfe-tools/environment.ts | 2 +- tools/pfe-tools/package.json | 4 +- tools/pfe-tools/react/generate-wrappers.ts | 2 +- tools/pfe-tools/ssr/global.ts | 2 +- tools/pfe-tools/ssr/shims.ts | 8 +- tools/pfe-tools/ssr/ssr.ts | 2 +- tools/pfe-tools/test/get-composed-text.ts | 2 +- .../pfe-tools/test/playwright/PfeDemoPage.ts | 8 +- tools/pfe-tools/test/playwright/SSRPage.ts | 2 +- tools/pfe-tools/test/utils.ts | 2 +- tsconfig.settings.json | 2 +- 99 files changed, 770 insertions(+), 596 deletions(-) create mode 100644 .changeset/wide-guests-speak.md delete mode 100644 @types/colorjs.io/index.d.ts diff --git a/.changeset/wide-guests-speak.md b/.changeset/wide-guests-speak.md new file mode 100644 index 0000000000..bbda4244f3 --- /dev/null +++ b/.changeset/wide-guests-speak.md @@ -0,0 +1,4 @@ +--- +"@patternfly/eslint-config-elements": major +--- +Require `@typescript-eslint` ^8.0.0 diff --git a/@types/colorjs.io/index.d.ts b/@types/colorjs.io/index.d.ts deleted file mode 100644 index c23d572828..0000000000 --- a/@types/colorjs.io/index.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -declare module 'colorjs.io' { - - export default class Color { - constructor(str: string); - toString(options?: { format: 'hex'|'rgb'|'rgba'|'hsl'|'hsla' }): string; - } - -} diff --git a/core/pfe-core/controllers/cascade-controller.ts b/core/pfe-core/controllers/cascade-controller.ts index d79ef0b842..bde105cb07 100644 --- a/core/pfe-core/controllers/cascade-controller.ts +++ b/core/pfe-core/controllers/cascade-controller.ts @@ -20,13 +20,14 @@ export class CascadeController implements ReactiveCon private logger: Logger; - static instances = new WeakMap>(); + static instances: WeakMap> = + new WeakMap>(); - mo = new MutationObserver(this.parse); + mo: MutationObserver = new MutationObserver(this.parse); - cache = new Map(); + cache: Map = new Map(); - constructor(public host: E, public options?: Options) { + constructor(public host: E, public options?: Options | undefined) { this.class = host.constructor as typeof ReactiveElement; this.logger = new Logger(this.host); CascadeController.instances.set(host, this); @@ -38,16 +39,16 @@ export class CascadeController implements ReactiveCon this.cascadeProperties = debounce(this.cascadeProperties, 1); } - hostUpdated() { + hostUpdated(): void { this.cascadeProperties(); } - hostConnected() { + hostConnected(): void { this.mo.observe(this.host, { attributes: true, childList: true }); this.cascadeProperties(); } - hostDisconnected() { + hostDisconnected(): void { this.mo.disconnect(); } @@ -56,7 +57,7 @@ export class CascadeController implements ReactiveCon * Attribute updates/additions are handled by the attribute callback * @param [nodeList=this.host.children] */ - cascadeProperties(nodeList: HTMLCollection | NodeList = this.host.children) { + cascadeProperties(nodeList: HTMLCollection | NodeList = this.host.children): void { if (this.host.isConnected) { const selectors = this.cache.keys(); @@ -93,7 +94,7 @@ export class CascadeController implements ReactiveCon * @param propName * @param cascade */ - initProp(propName: string, cascade: string | string[]) { + initProp(propName: string, cascade: string | string[]): void { for (const nodeItem of [cascade].flat(Infinity).filter(Boolean) as string[]) { const { attribute } = this.class.getPropertyOptions(propName); diff --git a/core/pfe-core/controllers/css-variable-controller.ts b/core/pfe-core/controllers/css-variable-controller.ts index 4070f5a57e..ba21f4b9d8 100644 --- a/core/pfe-core/controllers/css-variable-controller.ts +++ b/core/pfe-core/controllers/css-variable-controller.ts @@ -8,10 +8,10 @@ export class CssVariableController implements ReactiveController { } private parseProperty(name: string) { - return name.substr(0, 2) !== '--' ? `--${name}` : name; + return name.substring(0, 2) !== '--' ? `--${name}` : name; } - getVariable(name: string) { + getVariable(name: string): string | null { return this.style.getPropertyValue(this.parseProperty(name)).trim() || null; } diff --git a/core/pfe-core/controllers/floating-dom-controller.ts b/core/pfe-core/controllers/floating-dom-controller.ts index 5638e0d9f7..3bb9c7602a 100644 --- a/core/pfe-core/controllers/floating-dom-controller.ts +++ b/core/pfe-core/controllers/floating-dom-controller.ts @@ -64,19 +64,19 @@ export class FloatingDOMController implements ReactiveController { } /** The crosswise alignment of the invoker on which to display the floating DOM */ - get alignment() { + get alignment(): Alignment { return this.#alignment ?? 'center'; } /** The side of the invoker on which to display the floating DOM */ - get anchor() { + get anchor(): Anchor { return this.#anchor ?? ''; } /** * When true, the floating DOM is visible */ - get open() { + get open(): boolean { return this.#open; } @@ -106,7 +106,7 @@ export class FloatingDOMController implements ReactiveController { }; } - hostDisconnected() { + hostDisconnected(): void { this.#cleanup?.(); } @@ -175,7 +175,7 @@ export class FloatingDOMController implements ReactiveController { * @param options.flip * @param options.fallbackPlacements * */ - async show({ offset, placement, flip, fallbackPlacements }: ShowOptions = {}) { + async show({ offset, placement, flip, fallbackPlacements }: ShowOptions = {}): Promise { const invoker = this.#invoker; const content = this.#content; if (!invoker || !content) { @@ -194,7 +194,7 @@ export class FloatingDOMController implements ReactiveController { } /** Hide the floating DOM */ - async hide() { + async hide(): Promise { await this.host.updateComplete; while (this.#opening && !this.open) { await new Promise(requestAnimationFrame); diff --git a/core/pfe-core/controllers/internals-controller.ts b/core/pfe-core/controllers/internals-controller.ts index f4bd13a1d8..64bbbcd9e6 100644 --- a/core/pfe-core/controllers/internals-controller.ts +++ b/core/pfe-core/controllers/internals-controller.ts @@ -98,6 +98,8 @@ export class InternalsController implements ReactiveController, ARIAMixin { @aria ariaAtomic: string | null = null; @aria ariaAutoComplete: string | null = null; @aria ariaBusy: string | null = null; + @aria ariaBrailleLabel: string | null = null; + @aria ariaBrailleRoleDescription: string | null = null; @aria ariaChecked: string | null = null; @aria ariaColCount: string | null = null; @aria ariaColIndex: string | null = null; @@ -154,7 +156,7 @@ export class InternalsController implements ReactiveController, ARIAMixin { @aria ariaOwnsElements: Element[] | null = null; /** True when the control is disabled via it's containing fieldset element */ - get formDisabled() { + get formDisabled(): boolean { if (isServer) { return this._formDisabled; } else { @@ -162,16 +164,16 @@ export class InternalsController implements ReactiveController, ARIAMixin { } } - get labels() { + get labels(): NodeList { return this.internals.labels; } - get validity() { + get validity(): ValidityState { return this.internals.validity; } /** A best-attempt based on observed behaviour in FireFox 115 on fedora 38 */ - get computedLabelText() { + get computedLabelText(): string { return this.internals.ariaLabel || Array.from(this.internals.labels as NodeListOf) .reduce((acc, label) => @@ -253,27 +255,27 @@ export class InternalsController implements ReactiveController, ARIAMixin { hostConnected?(): void; - setFormValue(...args: Parameters) { + setFormValue(...args: Parameters): void { return this.internals.setFormValue(...args); } - setValidity(...args: Parameters) { + setValidity(...args: Parameters): void { return this.internals.setValidity(...args); } - checkValidity(...args: Parameters) { + checkValidity(...args: Parameters): boolean { return this.internals.checkValidity(...args); } - reportValidity(...args: Parameters) { + reportValidity(...args: Parameters): boolean { return this.internals.reportValidity(...args); } - submit() { + submit(): void { this.internals.form?.requestSubmit(); } - reset() { + reset(): void { this.internals.form?.reset(); } } diff --git a/core/pfe-core/controllers/light-dom-controller.ts b/core/pfe-core/controllers/light-dom-controller.ts index 3838180431..e53d11cd5c 100644 --- a/core/pfe-core/controllers/light-dom-controller.ts +++ b/core/pfe-core/controllers/light-dom-controller.ts @@ -12,14 +12,18 @@ export class LightDOMController implements ReactiveController { private logger: Logger; private initializer: () => void; - constructor(private host: ReactiveElement, initializer: () => void, private options?: Options) { + constructor( + private host: ReactiveElement, + initializer: () => void, + private options?: Options | undefined, + ) { this.initializer = initializer.bind(host); this.mo = new MutationObserver(this.initializer); this.logger = new Logger(this.host); host.addController(this); } - hostConnected() { + hostConnected(): void { if (this.hasLightDOM()) { this.initializer(); } else if (this.options?.emptyWarning) { @@ -29,7 +33,7 @@ export class LightDOMController implements ReactiveController { this.initObserver(); } - hostDisconnected() { + hostDisconnected(): void { this.mo.disconnect(); } diff --git a/core/pfe-core/controllers/listbox-controller.ts b/core/pfe-core/controllers/listbox-controller.ts index ec147a8e50..b89efe79d9 100644 --- a/core/pfe-core/controllers/listbox-controller.ts +++ b/core/pfe-core/controllers/listbox-controller.ts @@ -87,27 +87,27 @@ export class ListboxController implements ReactiveCont disabled = false; /** Current active descendant in listbox */ - get activeItem() { + get activeItem(): Item | undefined { return this.options.find(option => option === this._options.a11yController.activeItem) || this._options.a11yController.firstItem; } - get nextItem() { + get nextItem(): Item | undefined { return this._options.a11yController.nextItem; } - get options() { + get options(): Item[] { return this.#items; } /** * array of options which are selected */ - get selectedOptions() { + get selectedOptions(): Item[] { return this.options.filter(option => this._options.isSelected(option)); } - get value() { + get value(): Item | Item[] { const [firstItem] = this.selectedOptions; return this._options.multi ? this.selectedOptions : firstItem; } @@ -116,7 +116,7 @@ export class ListboxController implements ReactiveCont return this._options.getHTMLElement(); } - async hostConnected() { + async hostConnected(): Promise { if (!this.#listening) { await this.host.updateComplete; this.element?.addEventListener('click', this.#onClick); @@ -127,7 +127,7 @@ export class ListboxController implements ReactiveCont } } - hostUpdated() { + hostUpdated(): void { this.element?.setAttribute('role', 'listbox'); this.element?.setAttribute('aria-disabled', String(!!this.disabled)); this.element?.setAttribute('aria-multi-selectable', String(!!this._options.multi)); @@ -140,7 +140,7 @@ export class ListboxController implements ReactiveCont } } - hostDisconnected() { + hostDisconnected(): void { this.element?.removeEventListener('click', this.#onClick); this.element?.removeEventListener('focus', this.#onFocus); this.element?.removeEventListener('keydown', this.#onKeydown); @@ -330,7 +330,7 @@ export class ListboxController implements ReactiveCont * sets the listbox value based on selected options * @param value item or items */ - setValue(value: Item | Item[]) { + setValue(value: Item | Item[]): void { const selected = Array.isArray(value) ? value : [value]; const [firstItem = null] = selected; for (const option of this.options) { @@ -345,7 +345,7 @@ export class ListboxController implements ReactiveCont * register's the host's Item elements as listbox controller items * @param options items */ - setOptions(options: Item[]) { + setOptions(options: Item[]): void { const oldOptions = [...this.#items]; this.#items = options; this.#optionsChanged(oldOptions); diff --git a/core/pfe-core/controllers/logger.ts b/core/pfe-core/controllers/logger.ts index 4e5bad5ef2..d7cf7e95e8 100644 --- a/core/pfe-core/controllers/logger.ts +++ b/core/pfe-core/controllers/logger.ts @@ -19,7 +19,7 @@ export class Logger implements ReactiveController { * @example Logger.debugLog(true); * @param [preference=null] */ - static debugLog(preference = null) { + static debugLog(preference = null): boolean { // wrap localStorage references in a try/catch; merely referencing it can // throw errors in some locked down environments try { @@ -28,7 +28,7 @@ export class Logger implements ReactiveController { localStorage.pfeLog = !!preference; } return localStorage.pfeLog === 'true'; - } catch (e) { + } catch { return Logger.logDebug; } } @@ -40,7 +40,7 @@ export class Logger implements ReactiveController { * @example Logger.debug("Hello"); * @param msgs console.log params */ - static debug(...msgs: unknown[]) { + static debug(...msgs: unknown[]): void { if (Logger.debugLog()) { console.debug(...msgs); } @@ -51,7 +51,7 @@ export class Logger implements ReactiveController { * @example Logger.info("Hello"); * @param msgs console.log params */ - static info(...msgs: unknown[]) { + static info(...msgs: unknown[]): void { if (Logger.debugLog()) { console.info(...msgs); } @@ -62,7 +62,7 @@ export class Logger implements ReactiveController { * @example Logger.log("Hello"); * @param msgs console.log params */ - static log(...msgs: unknown[]) { + static log(...msgs: unknown[]): void { if (Logger.debugLog()) { console.log(...msgs); } @@ -73,7 +73,7 @@ export class Logger implements ReactiveController { * @example Logger.warn("Hello"); * @param msgs console.log params */ - static warn(...msgs: unknown[]) { + static warn(...msgs: unknown[]): void { console.warn(...msgs); } @@ -83,7 +83,7 @@ export class Logger implements ReactiveController { * @example Logger.error("Hello"); * @param msgs console.log params */ - static error(...msgs: unknown[]) { + static error(...msgs: unknown[]): void { console.error([...msgs].join(' ')); } @@ -94,7 +94,7 @@ export class Logger implements ReactiveController { * @example this.logger.log("Hello"); * @param msgs console.log params */ - debug(...msgs: unknown[]) { + debug(...msgs: unknown[]): void { Logger.debug(this.prefix, ...msgs); } @@ -103,7 +103,7 @@ export class Logger implements ReactiveController { * @example this.logger.log("Hello"); * @param msgs console.log params */ - info(...msgs: unknown[]) { + info(...msgs: unknown[]): void { Logger.info(this.prefix, ...msgs); } @@ -112,7 +112,7 @@ export class Logger implements ReactiveController { * @example this.logger.log("Hello"); * @param msgs console.log params */ - log(...msgs: unknown[]) { + log(...msgs: unknown[]): void { Logger.log(this.prefix, ...msgs); } @@ -122,7 +122,7 @@ export class Logger implements ReactiveController { * @example this.logger.warn("Hello"); * @param msgs console.log params */ - warn(...msgs: unknown[]) { + warn(...msgs: unknown[]): void { Logger.warn(this.prefix, ...msgs); } @@ -132,7 +132,7 @@ export class Logger implements ReactiveController { * @example this.logger.error("Hello"); * @param msgs console.log params */ - error(...msgs: unknown[]) { + error(...msgs: unknown[]): void { Logger.error(this.prefix, ...msgs); } @@ -145,7 +145,7 @@ export class Logger implements ReactiveController { Logger.instances.set(host, this); } - hostConnected() { + hostConnected(): void { this.debug('connected'); } } diff --git a/core/pfe-core/controllers/overflow-controller.ts b/core/pfe-core/controllers/overflow-controller.ts index 1b9e1d49e8..368922b4b0 100644 --- a/core/pfe-core/controllers/overflow-controller.ts +++ b/core/pfe-core/controllers/overflow-controller.ts @@ -63,7 +63,7 @@ export class OverflowController implements ReactiveController { constructor( // TODO: widen this type to ReactiveControllerHost public host: ReactiveElement, - private options?: Options, + private options?: Options | undefined, ) { this.#hideOverflowButtons = options?.hideOverflowButtons ?? false; this.#scrollTimeoutDelay = options?.scrollTimeoutDelay ?? 0; @@ -102,18 +102,18 @@ export class OverflowController implements ReactiveController { } } - init(container: HTMLElement, items: HTMLElement[]) { + init(container: HTMLElement, items: HTMLElement[]): void { this.#container = container; // convert HTMLCollection to HTMLElement[] this.#items = items; } - onScroll = () => { + onScroll = (): void => { clearTimeout(this.#scrollTimeout); this.#scrollTimeout = setTimeout(() => this.#setOverflowState(), this.#scrollTimeoutDelay); }; - scrollLeft() { + scrollLeft(): void { if (!this.#container) { return; } @@ -122,7 +122,7 @@ export class OverflowController implements ReactiveController { this.#setOverflowState(); } - scrollRight() { + scrollRight(): void { if (!this.#container) { return; } @@ -131,7 +131,7 @@ export class OverflowController implements ReactiveController { this.#setOverflowState(); } - update() { + update(): void { this.#setOverflowState(); } diff --git a/core/pfe-core/controllers/perf-controller.ts b/core/pfe-core/controllers/perf-controller.ts index 7e7e38a1b4..f5e866065d 100644 --- a/core/pfe-core/controllers/perf-controller.ts +++ b/core/pfe-core/controllers/perf-controller.ts @@ -22,13 +22,13 @@ export class PerfController implements ReactiveController { performance.mark(`${this.markId}-defined`); } - hostUpdate() { + hostUpdate(): void { if (!this.hasMeasured) { this.measure(); } } - measure() { + measure(): void { this.hasMeasured = true; performance.mark(`${this.markId}-rendered`); diff --git a/core/pfe-core/controllers/property-observer-controller.ts b/core/pfe-core/controllers/property-observer-controller.ts index 0e5d0b6698..0703f8efb1 100644 --- a/core/pfe-core/controllers/property-observer-controller.ts +++ b/core/pfe-core/controllers/property-observer-controller.ts @@ -1,6 +1,6 @@ import type { ReactiveController, ReactiveElement } from 'lit'; -export const observedController = Symbol('observed properties controller'); +export const observedController: unique symbol = Symbol('observed properties controller'); export type ChangeCallback = ( this: T, @@ -33,7 +33,7 @@ export class PropertyObserverController implements ReactiveController { } /** Set any cached valued accumulated between constructor and connectedCallback */ - hostUpdate() { + hostUpdate(): void { for (const [key, [methodName, [oldVal, newVal]]] of this.values) { // @ts-expect-error: be cool, typescript this.host[methodName as keyof ReactiveElement]?.(oldVal, newVal); @@ -42,11 +42,11 @@ export class PropertyObserverController implements ReactiveController { } /** Once the element has updated, we no longer need this controller, so we remove it */ - hostUpdated() { + hostUpdated(): void { this.host.removeController(this); } - cache(key: string, methodName: string, ...vals: [unknown, unknown]) { + cache(key: string, methodName: string, ...vals: [unknown, unknown]): void { this.values.set(key, [methodName, vals]); } } diff --git a/core/pfe-core/controllers/roving-tabindex-controller.ts b/core/pfe-core/controllers/roving-tabindex-controller.ts index b8c64fc652..afaa2fcaa3 100644 --- a/core/pfe-core/controllers/roving-tabindex-controller.ts +++ b/core/pfe-core/controllers/roving-tabindex-controller.ts @@ -28,12 +28,13 @@ export class RovingTabindexController< static of( host: ReactiveControllerHost, options: RovingTabindexControllerOptions & { getItems(): Item[] }, - ) { + ): RovingTabindexController { return new RovingTabindexController(host, options); } /** @internal */ - static elements = new WeakMap(); + static elements: WeakMap> = + new WeakMap(); /** active focusable element */ #activeItem?: Item; @@ -79,14 +80,14 @@ export class RovingTabindexController< /** * all items from array */ - get items() { + get items(): Item[] { return this.#items; } /** * all focusable items from array */ - get focusableItems() { + get focusableItems(): Item[] { return this.#focusableItems; } @@ -146,7 +147,7 @@ export class RovingTabindexController< this.updateItems(); } - hostUpdated() { + hostUpdated(): void { const oldContainer = this.#itemsContainer; const newContainer = this.#options.getHTMLElement(); if (oldContainer !== newContainer) { @@ -162,7 +163,7 @@ export class RovingTabindexController< /** * removes event listeners from items container */ - hostDisconnected() { + hostDisconnected(): void { this.#itemsContainer?.removeEventListener('keydown', this.#onKeydown); this.#itemsContainer = undefined; this.#gainedInitialFocus = false; @@ -268,7 +269,7 @@ export class RovingTabindexController< * Focuses next focusable item * @param items tabindex items */ - updateItems(items: Item[] = this.#options.getItems?.() ?? []) { + updateItems(items: Item[] = this.#options.getItems?.() ?? []): void { this.#items = items; const sequence = [ ...this.#items.slice(this.#itemIndex - 1), @@ -294,7 +295,7 @@ export class RovingTabindexController< * @param items tabindex items * @param itemsContainer */ - initItems(items: Item[], itemsContainer?: Element) { + initItems(items: Item[], itemsContainer?: Element): void { const element = itemsContainer ?? this.#options?.getItemContainer?.() ?? this.#options.getHTMLElement(); diff --git a/core/pfe-core/controllers/scroll-spy-controller.ts b/core/pfe-core/controllers/scroll-spy-controller.ts index a53b4d2fa5..89af9d2481 100644 --- a/core/pfe-core/controllers/scroll-spy-controller.ts +++ b/core/pfe-core/controllers/scroll-spy-controller.ts @@ -52,7 +52,7 @@ export class ScrollSpyController implements ReactiveController { .filter(this.#getHash); } - get root() { + get root(): Element | Document | null | undefined { return this.#root; } @@ -62,7 +62,7 @@ export class ScrollSpyController implements ReactiveController { this.#initIo(); } - get rootMargin() { + get rootMargin(): string | undefined { return this.#rootMargin; } @@ -72,7 +72,7 @@ export class ScrollSpyController implements ReactiveController { this.#initIo(); } - get threshold() { + get threshold(): number | number[] { return this.#threshold; } @@ -96,7 +96,7 @@ export class ScrollSpyController implements ReactiveController { this.#getHash = options?.getHash ?? ((el: Element) => el.getAttribute('href')); } - hostConnected() { + hostConnected(): void { this.#initIo(); } @@ -157,7 +157,7 @@ export class ScrollSpyController implements ReactiveController { * Explicitly set the active item * @param link usually an `
` */ - public async setActive(link: EventTarget | null) { + public async setActive(link: EventTarget | null): Promise { this.#force = true; this.#setActive(link); let sawActive = false; diff --git a/core/pfe-core/controllers/slot-controller.ts b/core/pfe-core/controllers/slot-controller.ts index 2dc7b54e25..519adf514d 100644 --- a/core/pfe-core/controllers/slot-controller.ts +++ b/core/pfe-core/controllers/slot-controller.ts @@ -50,9 +50,10 @@ const isSlot = : child.getAttribute('slot') === n; export class SlotController implements ReactiveController { - public static default = Symbol('default slot'); + public static default = Symbol('default slot') satisfies symbol as symbol; + /** @deprecated use `default` */ - public static anonymous = this.default; + public static anonymous: symbol = this.default; #nodes = new Map(); @@ -84,7 +85,7 @@ export class SlotController implements ReactiveController { host.addController(this); } - async hostConnected() { + async hostConnected(): Promise { this.host.addEventListener('slotchange', this.#onSlotChange as EventListener); this.#firstUpdated = false; this.#mo.observe(this.host, { childList: true }); @@ -99,14 +100,14 @@ export class SlotController implements ReactiveController { this.host.requestUpdate(); } - hostUpdated() { + hostUpdated(): void { if (!this.#firstUpdated) { this.#slotNames.forEach(this.#initSlot); this.#firstUpdated = true; } } - hostDisconnected() { + hostDisconnected(): void { this.#mo.disconnect(); } diff --git a/core/pfe-core/controllers/tabs-aria-controller.ts b/core/pfe-core/controllers/tabs-aria-controller.ts index 176b8b1403..c4ef7e366a 100644 --- a/core/pfe-core/controllers/tabs-aria-controller.ts +++ b/core/pfe-core/controllers/tabs-aria-controller.ts @@ -70,12 +70,12 @@ export class TabsAriaController< } } - hostConnected() { + hostConnected(): void { this.#mo.observe(this.#element, { attributes: false, childList: true, subtree: false }); this.#onSlotchange(); } - hostUpdated() { + hostUpdated(): void { for (const [tab, panel] of this.#tabPanelMap) { panel.setAttribute('aria-labelledby', tab.id); tab.setAttribute('aria-controls', panel.id); diff --git a/core/pfe-core/controllers/timestamp-controller.ts b/core/pfe-core/controllers/timestamp-controller.ts index 51727d7d82..e6deb68b49 100644 --- a/core/pfe-core/controllers/timestamp-controller.ts +++ b/core/pfe-core/controllers/timestamp-controller.ts @@ -35,11 +35,11 @@ export class TimestampController implements ReactiveController { #host: ReactiveControllerHost; - get localeString() { + get localeString(): string { return this.#date.toLocaleString(this.#options.locale); } - get date() { + get date(): Date { return this.#date; } @@ -47,11 +47,11 @@ export class TimestampController implements ReactiveController { this.#date = new Date(string); } - get isoString() { + get isoString(): string { return this.#date.toISOString(); } - get time() { + get time(): string { if (this.#options.relative) { return this.#getTimeRelative(); } else { @@ -127,7 +127,7 @@ export class TimestampController implements ReactiveController { return typeof (units) !== 'undefined' ? rtf.format(tense * qty, units) : 'just now'; } - set(prop: PropertyKey, value: unknown) { + set(prop: PropertyKey, value: unknown): void { if (TimestampController.#isTimestampOptionKey(prop)) { // @ts-expect-error: seems typescript compiler isn't up to the task here this.#options[prop] = value; diff --git a/core/pfe-core/core.ts b/core/pfe-core/core.ts index 21a3da623a..11d787529a 100644 --- a/core/pfe-core/core.ts +++ b/core/pfe-core/core.ts @@ -25,14 +25,14 @@ function makeConverter( * A LitElement property converter which represents a list of numbers as a comma separated string * @see https://lit.dev/docs/components/properties/#conversion-converter */ -export const NumberListConverter = +export const NumberListConverter: ComplexAttributeConverter = makeConverter(x => parseInt(x?.trim(), 10)); /** * A LitElement property converter which represents a list of strings as a comma separated string * @see https://lit.dev/docs/components/properties/#conversion-converter */ -export const StringListConverter = +export const StringListConverter: ComplexAttributeConverter = makeConverter(x => x.trim()); /** diff --git a/core/pfe-core/decorators/deprecation.ts b/core/pfe-core/decorators/deprecation.ts index 2147701260..73be32fa44 100644 --- a/core/pfe-core/decorators/deprecation.ts +++ b/core/pfe-core/decorators/deprecation.ts @@ -18,11 +18,13 @@ export type DeprecationDeclaration = PropertyDeclaration * @deprecation('colorPalette') color?: ColorPalette; * ``` */ -export function deprecation(options: DeprecationDeclaration) { +export function deprecation( + options: DeprecationDeclaration, +) { return function( proto: Partial>, key: string & keyof T - ) { + ): void { const { alias, ...deprecationOptions } = options; const klass = (proto.constructor as typeof ReactiveElement); const declaration = klass.getPropertyOptions(alias); diff --git a/core/pfe-core/decorators/initializer.ts b/core/pfe-core/decorators/initializer.ts index 25192d5748..a041451f97 100644 --- a/core/pfe-core/decorators/initializer.ts +++ b/core/pfe-core/decorators/initializer.ts @@ -11,7 +11,7 @@ import { LightDOMController } from '../controllers/light-dom-controller.js'; * @param options Set `observe` to `false` to skip mutation observer setup, or pass a MutationObserverInit as options */ export function initializer(options?: Options) { - return function(proto: T, key: string) { + return function(proto: T, key: string): void { // @TODO: allow multiple initializers (proto.constructor as typeof ReactiveElement).addInitializer(instance => { const initializer = proto[key as keyof T] as unknown as () => void; diff --git a/core/pfe-core/decorators/observed.ts b/core/pfe-core/decorators/observed.ts index a290bb3d20..d0096b5662 100644 --- a/core/pfe-core/decorators/observed.ts +++ b/core/pfe-core/decorators/observed.ts @@ -65,7 +65,7 @@ export function observeProperty( proto: T, key: string & keyof T, callbackOrMethod?: ChangeCallback -) { +): void { const descriptor = Object.getOwnPropertyDescriptor(proto, key); Object.defineProperty(proto, key, { ...descriptor, diff --git a/core/pfe-core/decorators/time.ts b/core/pfe-core/decorators/time.ts index aa0f964a8f..bdb3f45dac 100644 --- a/core/pfe-core/decorators/time.ts +++ b/core/pfe-core/decorators/time.ts @@ -3,7 +3,11 @@ * @param tag - short string to identify the method name */ export function time(tag?: string) { - return function(_: unknown, key: string, descriptor: PropertyDescriptor) { + return function( + _: unknown, + key: string, + descriptor: PropertyDescriptor, + ): void { const { value: f } = descriptor ?? {}; if (!(typeof f === 'function')) { diff --git a/core/pfe-core/decorators/trace.ts b/core/pfe-core/decorators/trace.ts index 165bd8669a..7507ad5cdc 100644 --- a/core/pfe-core/decorators/trace.ts +++ b/core/pfe-core/decorators/trace.ts @@ -3,7 +3,11 @@ * @param tag log tag, prepended to outputs */ export function trace(tag?: string) { - return function(_: unknown, key: string, descriptor: PropertyDescriptor) { + return function( + _: unknown, + key: string, + descriptor: PropertyDescriptor, + ): void { const { value: f } = descriptor; descriptor.value = function(...args: any[]) { const x = f.call(this, ...args); diff --git a/core/pfe-core/functions/containsDeep.ts b/core/pfe-core/functions/containsDeep.ts index 9a00f2bd4d..b14454bdef 100644 --- a/core/pfe-core/functions/containsDeep.ts +++ b/core/pfe-core/functions/containsDeep.ts @@ -5,7 +5,10 @@ * @param container haystack * @param node needle */ -export function containsDeep(container: Element, node: Node) { +export function containsDeep( + container: Element, + node: Node, +): boolean { if (container.contains(node)) { return true; } else { diff --git a/core/pfe-core/functions/context.ts b/core/pfe-core/functions/context.ts index f7e8919454..2e109b6b2c 100644 --- a/core/pfe-core/functions/context.ts +++ b/core/pfe-core/functions/context.ts @@ -1,11 +1,13 @@ -import { ContextRoot, createContext } from '@lit/context'; +import { ContextRoot, createContext, type Context } from '@lit/context'; import { isServer } from 'lit'; let root: ContextRoot; function makeContextRoot() { const root = new ContextRoot(); - !isServer && root.attach(document.body); + if (!isServer) { + root.attach(document.body); + } return root; } @@ -15,7 +17,9 @@ function makeContextRoot() { * Always use this function when creating contexts that are shared with child elements. * @param args createContext args */ -export function createContextWithRoot(...args: Parameters) { +export function createContextWithRoot( + ...args: Parameters +): Context { root ??= makeContextRoot(); return createContext(...args); } diff --git a/core/pfe-core/functions/debounce.ts b/core/pfe-core/functions/debounce.ts index b66af5f44d..b367ef1f4d 100644 --- a/core/pfe-core/functions/debounce.ts +++ b/core/pfe-core/functions/debounce.ts @@ -12,7 +12,7 @@ export function debounce( immediate = false ) { let timeout: number | null; - return function(this: unknown, ...args: any[]) { + return function(this: unknown, ...args: any[]): void { // eslint-disable-next-line @typescript-eslint/no-this-alias const context = this; const later = function() { diff --git a/elements/pf-accordion/pf-accordion-header.ts b/elements/pf-accordion/pf-accordion-header.ts index c6d5f859d5..3ae5f97612 100644 --- a/elements/pf-accordion/pf-accordion-header.ts +++ b/elements/pf-accordion/pf-accordion-header.ts @@ -1,6 +1,6 @@ import type { PfAccordion } from './pf-accordion.js'; -import { LitElement, html } from 'lit'; +import { LitElement, html, type TemplateResult } from 'lit'; import { customElement } from 'lit/decorators/custom-element.js'; import { property } from 'lit/decorators/property.js'; @@ -96,9 +96,9 @@ export class PfAccordionHeaderChangeEvent extends Event { */ @customElement('pf-accordion-header') export class PfAccordionHeader extends LitElement { - static readonly styles = [style]; + static readonly styles: CSSStyleSheet[] = [style]; - static override readonly shadowRootOptions = { + static override readonly shadowRootOptions: ShadowRootInit = { ...LitElement.shadowRootOptions, delegatesFocus: true, }; @@ -123,14 +123,14 @@ export class PfAccordionHeader extends LitElement { #slots = new SlotController(this, 'accents', null); - override connectedCallback() { + override connectedCallback(): void { super.connectedCallback(); this.hidden = true; this.id ||= getRandomId(this.localName); this.#initHeader(); } - override render() { + override render(): TemplateResult<1> { const headingText = this.headingText?.trim() ?? this.#header?.textContent?.trim(); const content = html`