diff --git a/scripts/shared.js b/scripts/shared.js index a67fbad9..dcdba6e5 100644 --- a/scripts/shared.js +++ b/scripts/shared.js @@ -1,3 +1,4 @@ +/** Gets an array of components from a CEM object. */ export function getAllComponents(metadata) { const allComponents = []; diff --git a/src/components/icon/library.ts b/src/components/icon/library.ts index 2c1dbad6..ee842ab4 100644 --- a/src/components/icon/library.ts +++ b/src/components/icon/library.ts @@ -13,18 +13,22 @@ export interface IconLibrary { let registry: IconLibrary[] = [defaultLibrary, systemLibrary]; let watchedIcons: SlIcon[] = []; +/** Adds an icon to the list of watched icons. */ export function watchIcon(icon: SlIcon) { watchedIcons.push(icon); } +/** Removes an icon from the list of watched icons. */ export function unwatchIcon(icon: SlIcon) { watchedIcons = watchedIcons.filter(el => el !== icon); } +/** Returns a library from the registry. */ export function getIconLibrary(name?: string) { return registry.find(lib => lib.name === name); } +/** Adds an icon library to the registry, or overrides an existing one. */ export function registerIconLibrary( name: string, options: { resolver: IconLibraryResolver; mutator?: IconLibraryMutator } @@ -44,6 +48,7 @@ export function registerIconLibrary( }); } +/** Removes an icon library from the registry. */ export function unregisterIconLibrary(name: string) { registry = registry.filter(lib => lib.name !== name); } diff --git a/src/components/include/request.ts b/src/components/include/request.ts index c6764bbd..efcb818c 100644 --- a/src/components/include/request.ts +++ b/src/components/include/request.ts @@ -6,6 +6,7 @@ interface IncludeFile { const includeFiles = new Map>(); +/** Fetches an include file from a remote source. Caching is enabled so the origin is only pinged once. */ export function requestInclude(src: string, mode: 'cors' | 'no-cors' | 'same-origin' = 'cors'): Promise { if (includeFiles.has(src)) { return includeFiles.get(src)!; diff --git a/src/components/tab-panel/tab-panel.ts b/src/components/tab-panel/tab-panel.ts index 8cce8468..3e078991 100644 --- a/src/components/tab-panel/tab-panel.ts +++ b/src/components/tab-panel/tab-panel.ts @@ -1,12 +1,13 @@ import { html } from 'lit'; import { customElement, property } from 'lit/decorators.js'; import { classMap } from 'lit/directives/class-map.js'; -import { autoIncrement } from '../../internal/auto-increment'; import ShoelaceElement from '../../internal/shoelace-element'; import { watch } from '../../internal/watch'; import styles from './tab-panel.styles'; import type { CSSResultGroup } from 'lit'; +let id = 0; + /** * @summary Tab panels are used inside [tab groups](/components/tab-group) to display tabbed content. * @@ -23,7 +24,7 @@ import type { CSSResultGroup } from 'lit'; export default class SlTabPanel extends ShoelaceElement { static styles: CSSResultGroup = styles; - private readonly attrId = autoIncrement(); + private readonly attrId = ++id; private readonly componentId = `sl-tab-panel-${this.attrId}`; /** The tab panel's name. */ diff --git a/src/components/tab/tab.ts b/src/components/tab/tab.ts index e0541b6a..3df5bc23 100644 --- a/src/components/tab/tab.ts +++ b/src/components/tab/tab.ts @@ -1,7 +1,6 @@ import { html } from 'lit'; import { customElement, property, query } from 'lit/decorators.js'; import { classMap } from 'lit/directives/class-map.js'; -import { autoIncrement } from '../../internal/auto-increment'; import ShoelaceElement from '../../internal/shoelace-element'; import { watch } from '../../internal/watch'; import { LocalizeController } from '../../utilities/localize'; @@ -9,6 +8,8 @@ import '../icon-button/icon-button'; import styles from './tab.styles'; import type { CSSResultGroup } from 'lit'; +let id = 0; + /** * @summary Tabs are used inside [tab groups](/components/tab-group) to represent and activate [tab panels](/components/tab-panel). * @@ -32,7 +33,7 @@ export default class SlTab extends ShoelaceElement { @query('.tab') tab: HTMLElement; - private readonly attrId = autoIncrement(); + private readonly attrId = ++id; private readonly componentId = `sl-tab-${this.attrId}`; /** The name of the tab panel this tab is associated with. The panel must be located in the same tab group. */ diff --git a/src/internal/animate.ts b/src/internal/animate.ts index 217957fd..bc86c575 100644 --- a/src/internal/animate.ts +++ b/src/internal/animate.ts @@ -1,6 +1,6 @@ -// -// Animates an element using keyframes. Returns a promise that resolves after the animation completes or gets canceled. -// +/** + * Animates an element using keyframes. Returns a promise that resolves after the animation completes or gets canceled. + */ export function animateTo(el: HTMLElement, keyframes: Keyframe[], options?: KeyframeAnimationOptions) { return new Promise(resolve => { if (options?.duration === Infinity) { @@ -17,9 +17,7 @@ export function animateTo(el: HTMLElement, keyframes: Keyframe[], options?: Keyf }); } -// -// Parses a CSS duration and returns the number of milliseconds. -// +/** Parses a CSS duration and returns the number of milliseconds. */ export function parseDuration(delay: number | string) { delay = delay.toString().toLowerCase(); @@ -34,17 +32,15 @@ export function parseDuration(delay: number | string) { return parseFloat(delay); } -// -// Tells if the user has enabled the "reduced motion" setting in their browser or OS. -// +/** Tells if the user has enabled the "reduced motion" setting in their browser or OS. */ export function prefersReducedMotion() { const query = window.matchMedia('(prefers-reduced-motion: reduce)'); return query.matches; } -// -// Stops all active animations on the target element. Returns a promise that resolves after all animations are canceled. -// +/** + * Stops all active animations on the target element. Returns a promise that resolves after all animations are canceled. + */ export function stopAnimations(el: HTMLElement) { return Promise.all( el.getAnimations().map(animation => { @@ -59,8 +55,10 @@ export function stopAnimations(el: HTMLElement) { ); } -// We can't animate `height: auto`, but we can calculate the height and shim keyframes by replacing it with the -// element's scrollHeight before the animation. +/** + * We can't animate `height: auto`, but we can calculate the height and shim keyframes by replacing it with the + * element's scrollHeight before the animation. + */ export function shimKeyframesHeightAuto(keyframes: Keyframe[], calculatedHeight: number) { return keyframes.map(keyframe => ({ ...keyframe, diff --git a/src/internal/auto-increment.ts b/src/internal/auto-increment.ts deleted file mode 100644 index 6b968915..00000000 --- a/src/internal/auto-increment.ts +++ /dev/null @@ -1,5 +0,0 @@ -let id = 0; - -export function autoIncrement(): number { - return ++id; -} diff --git a/src/internal/drag.ts b/src/internal/drag.ts index 35088400..8e3ea64c 100644 --- a/src/internal/drag.ts +++ b/src/internal/drag.ts @@ -11,6 +11,7 @@ interface DragOptions { initialEvent: PointerEvent; } +/** Begins listening for dragging. */ export function drag(container: HTMLElement, options?: Partial) { function move(pointerEvent: PointerEvent) { const dims = container.getBoundingClientRect(); diff --git a/src/internal/math.ts b/src/internal/math.ts index 42e9495a..f82b5dd9 100644 --- a/src/internal/math.ts +++ b/src/internal/math.ts @@ -1,6 +1,4 @@ -// -// Ensures a number stays within a minimum and maximum value -// +/** Ensures a number stays within a minimum and maximum value */ export function clamp(value: number, min: number, max: number) { if (value < min) { return min; diff --git a/src/internal/offset.ts b/src/internal/offset.ts index 2148aa95..c5b2c917 100644 --- a/src/internal/offset.ts +++ b/src/internal/offset.ts @@ -1,10 +1,10 @@ -// -// Returns an element's offset relative to its parent. Similar to element.offsetTop and element.offsetLeft, except the -// parent doesn't have to be positioned relative or absolute. -// -// NOTE: This was created to work around what appears to be a bug in Chrome where a slotted element's offsetParent -// seems to ignore elements inside the surrounding shadow DOM: https://bugs.chromium.org/p/chromium/issues/detail?id=920069 -// +/** + * Returns an element's offset relative to its parent. Similar to element.offsetTop and element.offsetLeft, except the + * parent doesn't have to be positioned relative or absolute. + * + * NOTE: This was created to work around what appears to be a bug in Chrome where a slotted element's offsetParent seems + * to ignore elements inside the surrounding shadow DOM: https://bugs.chromium.org/p/chromium/issues/detail?id=920069 + */ export function getOffset(element: HTMLElement, parent: HTMLElement) { return { top: Math.round(element.getBoundingClientRect().top - parent.getBoundingClientRect().top), diff --git a/src/internal/scroll.ts b/src/internal/scroll.ts index 39ae665b..356c1fb4 100644 --- a/src/internal/scroll.ts +++ b/src/internal/scroll.ts @@ -2,18 +2,18 @@ import { getOffset } from './offset'; const locks = new Set(); -// -// Prevents body scrolling. Keeps track of which elements requested a lock so multiple levels of locking are possible -// without premature unlocking. -// +/** + * Prevents body scrolling. Keeps track of which elements requested a lock so multiple levels of locking are possible + * without premature unlocking. + */ export function lockBodyScrolling(lockingEl: HTMLElement) { locks.add(lockingEl); document.body.classList.add('sl-scroll-lock'); } -// -// Unlocks body scrolling. Scrolling will only be unlocked once all elements that requested a lock call this method. -// +/** + * Unlocks body scrolling. Scrolling will only be unlocked once all elements that requested a lock call this method. + */ export function unlockBodyScrolling(lockingEl: HTMLElement) { locks.delete(lockingEl); @@ -22,9 +22,9 @@ export function unlockBodyScrolling(lockingEl: HTMLElement) { } } -// -// Scrolls an element into view of its container. If the element is already in view, nothing will happen. -// +/** + * Scrolls an element into view of its container. If the element is already in view, nothing will happen. + */ export function scrollIntoView( element: HTMLElement, container: HTMLElement, diff --git a/src/internal/string.ts b/src/internal/string.ts index 55f682a8..769a026a 100644 --- a/src/internal/string.ts +++ b/src/internal/string.ts @@ -1,3 +1,4 @@ +/** Converts the first letter of a string to uppercase */ export function uppercaseFirstLetter(string: string) { return string.charAt(0).toUpperCase() + string.slice(1); } diff --git a/src/internal/watch.ts b/src/internal/watch.ts index bc18fa80..2cfb796c 100644 --- a/src/internal/watch.ts +++ b/src/internal/watch.ts @@ -1,17 +1,3 @@ -// @watch decorator -// -// Runs when an observed property changes, e.g. @property or @state, but before the component updates. -// -// To wait for an update to complete after a change occurs, use `await this.updateComplete` in the handler. To start -// watching after the initial update/render, use `{ waitUntilFirstUpdate: true }` or `this.hasUpdated` in the handler. -// -// Usage: -// -// @watch('propName') -// handlePropChange(oldValue, newValue) { -// ... -// } - import type { LitElement } from 'lit'; type UpdateHandler = (prev?: unknown, next?: unknown) => void; @@ -29,6 +15,18 @@ interface WatchOptions { waitUntilFirstUpdate?: boolean; } +/** + * Runs when an observed property changes, e.g. @property or @state, but before the component updates. + * To wait for an update to complete after a change occurs, use `await this.updateComplete` in the handler. To start + * watching after the initial update/render, use `{ waitUntilFirstUpdate: true }` or `this.hasUpdated` in the handler. + * + * Usage: + * + * @watch('propName') + * handlePropChange(oldValue, newValue) { + * ... + * } + */ export function watch(propName: string, options?: WatchOptions) { const resolvedOptions: Required = { waitUntilFirstUpdate: false, diff --git a/src/utilities/animation-registry.ts b/src/utilities/animation-registry.ts index 696d1185..35ae85ac 100644 --- a/src/utilities/animation-registry.ts +++ b/src/utilities/animation-registry.ts @@ -38,24 +38,20 @@ function getLogicalAnimation(animation: ElementAnimation, dir: string) { return animation; } -// -// Sets a default animation. Components should use the `name.animation` for primary animations and `name.part.animation` -// for secondary animations, e.g. `dialog.show` and `dialog.overlay.show`. For modifiers, use `drawer.showTop`. -// +/** + * Sets a default animation. Components should use the `name.animation` for primary animations and `name.part.animation` + * for secondary animations, e.g. `dialog.show` and `dialog.overlay.show`. For modifiers, use `drawer.showTop`. + */ export function setDefaultAnimation(animationName: string, animation: ElementAnimation | null) { defaultAnimationRegistry.set(animationName, ensureAnimation(animation)); } -// -// Sets a custom animation for the specified element. -// +/** Sets a custom animation for the specified element. */ export function setAnimation(el: Element, animationName: string, animation: ElementAnimation | null) { customAnimationRegistry.set(el, { ...customAnimationRegistry.get(el), [animationName]: ensureAnimation(animation) }); } -// -// Gets an element's animation. Falls back to the default if no animation is found. -// +/** Gets an element's animation. Falls back to the default if no animation is found. */ export function getAnimation(el: Element, animationName: string, options: GetAnimationOptions) { const customAnimation = customAnimationRegistry.get(el); diff --git a/src/utilities/base-path.ts b/src/utilities/base-path.ts index f0539ffa..7e193c4a 100644 --- a/src/utilities/base-path.ts +++ b/src/utilities/base-path.ts @@ -1,8 +1,6 @@ let basePath = ''; -/** - * Sets the library's base path to the specified directory. - */ +/** Sets the library's base path to the specified directory. */ export function setBasePath(path: string) { basePath = path; } @@ -16,7 +14,7 @@ export function setBasePath(path: string) { * (it probably makes the most sense to attach it to the Shoelace script, but it could also be on a bundle). The value * can be a local folder or it can point to a CORS-enabled endpoint such as a CDN. * - * + * * * Alternatively, you can set the base path manually using the exported setBasePath() function. */