Utilities
Reusable functions for improved workflow
Some components in Webcore comes with JavaScript API that let’s you dynamically handle components. Apart from this functionality, Webcore also exposes a couple of other utility functions that you can use in your own codebase to speed up your development workflow. You’ll find the following utility function in Webcore.
webcoreui. If you’d like to reuse some of the functionalities defined here in your own project without Webcore, you can find the implementations here. ClassNames
Use the classNames function to dynamically and conditionally generate valid CSS class names. The function expects an array of elements. You can create conditions inside the array using logical operators. The array elements will be concatenated into a single class name.
import { classNames } from 'webcoreui'
classNames(['avatar', true && 'borderless']) -> 'avatar borderless'classNames(['avatar', false && 'borderless', null]) -> 'avatar'const classNames: (classes: any[]) => stringCookies
To work with cookies, use the getCookie, setCookie, and removeCookie functions.
-
Getting cookies
import { getCookie } from 'webcoreui'getCookie('w-theme')Expects the name of the cookie as a string, and returns the value of the cookie if present. Returns
nullif no cookie is found. -
Setting cookies
import { setCookie } from 'webcoreui'setCookie('w-theme', 'theme-dark', 30)Sets the cookie for a specified duration. Expects, the name of the cookie as a string, the value of the cookie as a string, and the number of days in numbers. In the above example, the
w-themecookie will be set for 30 days before expiration with the value oftheme-dark. -
Removing cookies
import { removeCookie } from 'webcoreui'removeCookie('w-theme')Removes the specified cookied. Pass the name of the cookie as a string you’d like to remove. No value is returned from the function.
const setCookie: (name: string, value: string, days: number) => voidconst getCookie: (name: string) => string | nullconst removeCookie: (name: string) => voidDebounce
Use the debounce function to limit the rate at which a function is executed. Use for performance optimization for excessively executed functions, such as keyup, resize, or scroll events:
import { debounce } from 'webcoreui'
const callbackWithDebounce = debounce(() => { console.log('called with debounce')})
new ResizeObserver(() => { callbackWithDebounce()}).observe(document.body)
// Call `.cancel` to cancel a debounce earliercallbackWithDebounce.cancel()Pass the callback function to the debounce call that should be rate limited. Optionally, you can set a second parameter to configure the timeout for the debounce. By default, this is set to 100 milliseconds.
const debounce: <T extends (...args: any[]) => any>( fn: T, waitFor?: number) => { (...args: Parameters<T>): void cancel: () => void}DOM Utilities
Webcore provides the following DOM utility functions to make the work with DOM elements easier in Astro components:
-
Getting DOM elements
import { get } from 'webcoreui'const element = get('.selector') // Get a single DOM elementconst element = get('.selectors', true) // Get all DOM elements with the selectorUse the
getutility function to select DOM elements. Passtrueas the second parameter to get all DOM elements with the specified selector. The selector can be a valid HTML query selector. -
Adding event listeners
import { on } from 'webcoreui'on('button', 'click', () => console.log('Button clicked.'))To add event listeners in your Astro components, you can use the above utility function. It expects the following parameters:
selector: Pass a query selector as the first parameter where you want to attach the event listener. This can also be a variable that references an HTML element.event: Pass the event for the event listener.callback: Pass the callback function that should be executed once the event is triggered.
You can also use the
onutility function to attach events listeners to multiple elements by setting the fourth parameter totrue:Adding an event listener to all buttons import { on } from 'webcoreui'on('.my-buttons', 'click', () => console.log('Button clicked.'), true)This will query all elements with the
.my-buttonsselector, and add a click event listener to each one of them. -
Removing event listeners
import { on, off } from 'webcoreui'const fn = () => { ... }on('button', 'click', fn)off('button', 'click', fn)To remove event listeners, you can use the
offutility function. Pass the callback function as the third parameter that needs to be removed.
const get: (selector: string, all?: boolean) => Element | NodeListOf<Element> | nullconst on: ( selector: string | HTMLElement | Document, event: string, callback: any, all?: boolean) => voidconst off: ( selector: string | HTMLElement | Document, event: string, fn: any, all?: boolean) => voidEvents
To work with custom events, use the dispatch and listen functions:
import { listen, dispatch } from 'webcoreui'
listen('theme-switched', theme => { console.log(theme) // 'theme-dark'})
dispatch('theme-switched', 'theme-dark')listen: Thelistenfunction expects the name of the event as a string for the first parameter, and a callback function as the second parameter. The callback function has access to the payload sent by thedispatchin the second parameter.dispatch: To send the event, calldispatchwith the name of the event of your choice. In the second parameter, you can send a payload along with the event. Anylistencall subscribed to the event will receive the payload when the event is triggered by thedispatchcall.
If you need to remove the listener later on, you can assign the listen function to a variable, and call the remove method:
import { listen, dispatch } from 'webcoreui'
const event = listen('theme-switched', theme => { console.log(theme) // 'theme-dark'})
dispatch('theme-switched', 'theme-dark')
// You can later remove the listener by calling .remove() on the eventevent.remove()Use the two utility functions in combination to share data between different parts of your application that are otherwise unrelated. This approach is known as the publish-subscribe design pattern, or pub/sub for short.
const dispatch: (event: string, detail: unknown) => voidconst listen: (event: string, callback: (e: any) => unknown) => { remove: () => void}Interactivity
Use the bodyFreeze function to prevent the window from scrolling. This could be useful in cases you want to prevent scrolling when a popup or dialog blocks the main content.
import { bodyFreeze } from 'webcoreui'
bodyFreeze() // Freezes the window from scrollingbodyFreeze(false) // Unfreezes the windowconst bodyFreeze: (freeze: boolean) => voidBreakpoints
To get the currently active breakpoint from JavaScript you can use the getBreakpoint function:
import { getBreakpoint } from 'webcoreui'
getBreakpoint() // Returns one of 'xs' | 'sm' | 'md' | 'lg'You can also read the active breakpoint’s value from the --w-breakpoint CSS variable. To use the function, you must have includeBreakpoints set to true in your CSS setup mixin. If you did not disabled it manually, this option is enabled by default.
const getBreakpoint: () => stringInterpolate
You can use the following math functions if you need to transform numbers in various ways:
clamp: Restrict a value to lie within a specified range.lerp: Find a value that is a given fraction between a start and end value.invlerp: Find the fraction at which a given value lies between a start and end value.interpolate: A combination oflerpandinvlerpto map values from one range to another.
-
Clamp
import { clamp } from 'webcoreui'// Clamp 50 between 0 and 100clamp(50, 0, 100) -> 50// Clamp 100 between 0 and 50clamp(100, 0, 50) -> 50// Clamp 50 between 100 and 200clamp(50, 100, 200) -> 100Use cases:
- User Input Validation: Ensuring that user inputs stay within a valid range, such as volume levels (0 to 100).
- Animation Control: Limiting the position or size of elements within the bounds of a container.
-
Lerp
import { lerp } from 'webcoreui'// 50% between 0 and 10lerp(0, 10, .5) -> 5// 50% between 0 and 100lerp(0, 100, .5) -> 50// 200% between 0 and 100lerp(0, 100, 2) -> 200// 20% between 100 and 200lerp(100, 200, .2) -> 120Use cases:
- Smooth Animations: Gradually moving an element from one position to another or transitioning between colors.
- Blending Values: Combining two values based on a weight.
-
Inverse Lerp
import { invlerp } from 'webcoreui'// Map 5 from [0, 10] to [0, 1]invlerp(0, 10, 5) -> .5// Map 50 from [0, 100] to [0, 1]invlerp(0, 100, 50) -> .5// Map 20 from [0, 100] to [0, 1]invlerp(0, 100, 20) -> .2// Map 120 from [100, 200] to [0, 1]invlerp(100, 200, 120) -> .2Use cases:
- Mapping Values: Mapping a value from one range to another, which is useful in normalization or data scaling.
- Progress Indicators: Determining the progress percentage of a task or loading bar based on the current value.
-
Interpolate
import { interpolate } from 'webcoreui'// Map 50 from [0, 100] to [0, 50]interpolate(50, [0, 100], [0, 50]) -> 25// Map 50 from [0, 100] to [100, 300]interpolate(50, [0, 100], [100, 300]) -> 200// Map 100 from [0, 200] to [0, 100]interpolate(100, [0, 200], [0, 100]) -> 50Use the
interpolatefunction if you need to provide both the input and output ranges.
const clamp = (num: number, min: number, max: number) => numberconst lerp = (start: number, end: number, value: number) => numberconst invlerp = (start: number, end: number, value: number) => numberconst interpolate = ( value: number, input: [start: number, end: number], output: [start: number, end: number],) => numberModals & Sheets
To open modals or sheets, you’ll need to create a Modal/Sheet component first:
<Button className="my-button">Open Modal</Button><Modal className="my-modal"> Modal with text only.</Modal><Button className="my-button">Open Sheet</Button><Sheet className="my-sheet"> Sheet with text only.</Sheet>Based on the above selectors, you can target this component to trigger it using the modal function:
import { modal } from 'webcoreui'
modal({ trigger: '.my-button', modal: '.my-modal'})import { modal } from 'webcoreui'
const modalInstance = modal('.my-modal')
// On button clickmodalInstance.open()import { closeModal } from 'webcoreui'
closeModal('.my-modal')You can open modals in two different ways:
- Open: Pass a configuration object with a
triggerproperty that specifies a query selector for a trigger element, and pass amodalproperty to target theModal/Sheetcomponent. Clicking on the trigger element will now open the component. - Open via JS: Pass a query selector to the
modalfunction that targets the component, and assign the function to a variable. You can call theopenmethod on the assigned variable. This lets you trigger the component programmatically, for example, after a network request finishes.
type ModalInstance = { open: (freeze?: boolean) => void close: () => void replaceWith: (modal: ModalInstance) => void remove: () => void}
type ModalCallback = { trigger: Element | null modal: HTMLElement}
type ModalConfig = { trigger: string modal: string onOpen?: (args: ModalCallback) => unknown onClose?: (args: ModalCallback) => unknown}
const modal: (config: ModalConfig | string) => ModalInstance | undefinedconst closeModal: (modal: string) => voidThe JavaScript API of the Modal and Sheet components are identical. To learn more about how to use the Modal component, visit its documentation. To learn more about how to use the Sheet component, you can find its documentation here.
Popovers
To create popovers, you’ll need to create a Popover component first:
<Button className="trigger-popover">Open popover</Button><Popover className="my-popover"> Popover with text only.</Popover>As popovers are attached to interactive elements, you’ll also need to create an interactive element, such as a button, that can trigger the popover. In this example, a Button component is used.
Based on the above selectors, you can target this popover to initialize it:
import { popover } from 'webcoreui'
popover({ trigger: '.trigger-popover', // Query selector for the button popover: '.my-popover' // Query selector for the popover})import { closePopover } from 'webcoreui'
closePopover('.my-popover')import { popover } from 'webcoreui'
const popoverInstance = popover({ trigger: '.trigger-popover', popover: '.my-popover'})
// Calling `.remove` will disable the popoverpopoverInstance.remove()Whenever the .trigger-popover button is clicked, it’ll open the .my-popover element. The popover function also returns a remove function that can be used to remove the created popover instance.
type PopoverPosition = 'top' | 'top-start' | 'top-end' | 'left' | 'left-start' | 'left-end' | 'right' | 'right-start' | 'right-end' | 'bottom' | 'bottom-start' | 'bottom-end'
type PopoverInstance = { remove: () => void}
type PopoverCallback = { trigger: HTMLElement popover: HTMLElement position: PopoverPosition | undefined}
type Popover = { trigger: string popover: string position?: PopoverPosition offset?: number closeOnBlur?: boolean closeOnEsc?: boolean onOpen?: (args: PopoverCallback) => unknown onClose?: (args: PopoverCallback) => unknown}
const popover: (config: Popover) => PopoverInstance | undefinedconst closePopover: (selector: string) => voidTo learn more about how to use the Popover component, visit its documentation.
Toasts
To dynamically show toasts, you’ll need to create a Toast component first:
<Toast className="my-toast"> Toast with text only.</Toast>Based on a selector, you can target this toast to trigger it:
import { toast } from 'webcoreui'
toast('.my-toast')import { hideToast } from 'webcoreui'
hideToast('.my-toast')import { setDefaultTimeout } from 'webcoreui'
setDefaultTimeout(3000)To configure the behavior of your toast, pass a configuration object to the toast function:
import { toast } from 'webcoreui'
toast({ element: '.my-toast', timeout: 10_000, title: 'Title set through JS', content: 'Content updated with JavaScript', position: 'bottom-left'})type Toast = { element: string timeout?: number title?: string content?: string position?: 'bottom-left' | 'top-left' | 'top-right' | 'bottom-full' | 'top-full'}
const setDefaultTimeout: (time: number) => numberconst toast: (config: Toast | string) => voidconst hideToast: (element: string) => voidTo learn more about how to use the Toast component, visit its documentation.
Request improvement for this page