Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@aria-ui/core

Package Overview
Dependencies
Maintainers
0
Versions
19
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@aria-ui/core - npm Package Compare versions

Comparing version 0.0.18 to 0.0.19

162

dist/index.d.ts

@@ -1,5 +0,5 @@

import { HTMLElement } from 'server-dom-shim';
import { HTMLElement as HTMLElement$1 } from 'server-dom-shim';
import { batch as batch$1, untracked as untracked$1 } from '@preact/signals-core';
import { AriaAttributes } from '@dddstack/ariatype-aria-attributes';
import { AriaRole } from '@dddstack/ariatype-aria-roles';
import { AriaAttributes } from '@ariatype/aria-attributes';
import { AriaRole } from '@ariatype/aria-roles';

@@ -11,3 +11,3 @@ /**

*/
interface ConnectableElement extends HTMLElement {
interface ConnectableElement extends HTMLElement$1 {
/**

@@ -105,2 +105,18 @@ * Registers a callback to be called when the element is connected to the DOM.

type ContextCallback<T> = (signal: Signal<T>) => void;
declare class ContextRequestEvent<T> extends Event {
readonly key: string | symbol;
readonly callback: ContextCallback<T>;
constructor(key: string | symbol, callback: ContextCallback<T>);
}
declare class ContextProviderEvent extends Event {
readonly key: string | symbol;
constructor(key: string | symbol);
}
declare global {
interface HTMLElementEventMap {
"aria-ui/context-request": ContextRequestEvent<unknown>;
"aria-ui/context-provider": ContextProviderEvent;
}
}
/**

@@ -152,3 +168,3 @@ * A context is a way to provide and consume signals in a HTML tree.

*/
declare function useAttribute(element: ConnectableElement, key: string, compute: () => string | number | undefined): VoidFunction;
declare function useAttribute(element: ConnectableElement, key: string, compute: () => string | number | undefined | null): VoidFunction;
/**

@@ -200,2 +216,67 @@ * Sets the computed attribute of the element when it's connected.

/**
* Defines options for an event.
*/
type EventDeclaration = {
/**
* Whether the event bubbles.
* @default false
*/
bubbles?: boolean;
/**
* Whether the event is cancelable.
* @default true
*/
cancelable?: boolean;
/**
* Whether the event is composed.
* @default false
*/
composed?: boolean;
};
/**
* Map of event types to EventDeclaration options.
*/
type EventDeclarations<Events extends {
[EventType in keyof Events]: CustomEvent;
}> = {
[EventType in keyof Required<Events>]: EventDeclaration;
};
declare function defineEmit<Events extends {
[EventType in keyof Events]: CustomEvent;
}>(element: HTMLElement, events: EventDeclarations<Events>): (type: keyof Events, detail: Events[keyof Events]["detail"]) => void;
/**
* Defines options for a property.
*/
type PropDeclaration<T = unknown> = {
/**
* The default value of the property.
*/
default: T;
/**
* Indicates how and whether the property becomes an observed attribute.
* If the value is `false`, the property is not added to `observedAttributes`.
* If true or absent, the kebab-case version of the property name is observed
* (e.g. `fooBar` becomes `foo-bar`). If a string, the string value is
* observed (e.g `attribute: 'custom-foo-bar'`).
*/
attribute?: boolean | string;
/**
* Called to convert an attribute value to a property
* value.
*/
fromAttribute?: (value: string | null) => T;
/**
* Called to convert a property value to an attribute value.
*/
toAttribute?: (value: T) => string | null;
};
/**
* Map of props to PropDeclaration options.
*/
type PropDeclarations<T extends Record<string, any> = Record<string, any>> = {
[K in keyof Required<T>]: PropDeclaration<T[K]>;
};
/**
* A plain object containing signals.

@@ -206,3 +287,3 @@ *

type SignalState<T extends object> = {
[K in keyof T]: Signal<T[K]>;
[K in keyof Required<T>]: Signal<T[K]>;
};

@@ -213,2 +294,4 @@ /**

* @group Props and States
*
* @deprecated
*/

@@ -220,4 +303,7 @@ declare function mapValues<T extends object>(signals: SignalState<T>): T;

* @group Props and States
*
* @deprecated
*/
declare function mapSignals<T extends object>(values: T): SignalState<T>;
declare function getStateFromProps<Props extends object>(props: PropDeclarations<Props>): SignalState<Props>;

@@ -230,5 +316,5 @@ /**

*/
declare class BaseElement extends HTMLElement implements ConnectableElement {
declare class BaseElement extends HTMLElement$1 implements ConnectableElement {
private _connectedCallbacks;
private _disconnectedCallback;
private _disconnectedCallbacks;
private _connected;

@@ -246,17 +332,41 @@ /**

*/
adoptedCallback(): void;
/**
* @hidden
*/
addConnectedCallback(callback: () => VoidFunction | void): void;
}
interface CustomElementOptions<Props extends {
[PropName in keyof Props]: unknown;
}, Events extends {
[EventType in keyof Events]: CustomEvent;
}> {
props: PropDeclarations<Props>;
events: EventDeclarations<Events>;
setup: (element: BaseElement, options: SetupOptions<Props, Events>) => void;
}
interface SetupOptions<Props extends {
[PropName in keyof Props]: unknown;
}, Events extends {
[EventType in keyof Events]: CustomEvent;
}> {
state: SignalState<Props>;
emit: EventEmitter<Events>;
}
type EventEmitter<Events extends {
[EventType in keyof Events]: CustomEvent;
}, EventType extends keyof Events = keyof Events> = (type: EventType extends string ? EventType : never, detail: EventType extends string ? Events[EventType]["detail"] : never) => void;
type BaseElementConstructor<Props extends {
[PropName in keyof Props]: unknown;
}> = new () => BaseElement & Props;
/**
* Create a custom element class.
* Defines a custom element constructor.
*
* @public
* @param options
*/
declare function ElementBuilder<Props extends object>(useElement: (host: ConnectableElement, state: SignalState<Props>) => void, defaultProps: Props): {
new (): BaseElement & Props;
prototype: HTMLElement;
};
declare function defineCustomElement<Props extends {
[PropName in keyof Props]: unknown;
}, Events extends {
[EventType in keyof Events]: CustomEvent;
}>({ props, events, setup, }: CustomElementOptions<Props, Events>): BaseElementConstructor<Props>;
/**
* Adds the given custom element to the custom element registry.
*/
declare function registerCustomElement(name: string, element: CustomElementConstructor): void;

@@ -271,16 +381,10 @@ /**

declare const emptyObjectSymbol: unique symbol;
/**
* Represents a strictly empty plain object, the `{}` value.
*
* When you annotate something as the type `{}`, it can be anything except
* `null` and `undefined`. This means that you cannot use `{}` to represent an
* empty plain object ([read more](https://stackoverflow.com/questions/47339869/typescript-empty-object-and-any-difference/52193484#52193484)).
*
* @public
* An interface thats can be used to register event listeners.
*/
interface EmptyObject {
[emptyObjectSymbol]?: never;
interface TypedEventTarget<EventType extends keyof DocumentEventMap> {
addEventListener: (type: EventType, listener: (event: DocumentEventMap[EventType]) => void) => void;
removeEventListener: (type: EventType, listener: (event: DocumentEventMap[EventType]) => void) => void;
}
export { BaseElement, type ConnectableElement, type Context, ElementBuilder, type EmptyObject, type ReadonlySignal, type Signal, type SignalState, type SignalValue, assignProps, batch, createComputed, createContext, createSignal, mapSignals, mapValues, untracked, useAnimationFrame, useAriaAttribute, useAriaRole, useAttribute, useEffect, useEventListener, useQuerySelector, useQuerySelectorAll, useStyle };
export { BaseElement, type BaseElementConstructor, type ConnectableElement, type Context, type CustomElementOptions, type EventDeclaration, type EventDeclarations, type EventEmitter, type PropDeclaration, type PropDeclarations, type ReadonlySignal, type SetupOptions, type Signal, type SignalState, type SignalValue, type TypedEventTarget, assignProps, batch, createComputed, createContext, createSignal, defineCustomElement, defineEmit, getStateFromProps, mapSignals, mapValues, registerCustomElement, untracked, useAnimationFrame, useAriaAttribute, useAriaRole, useAttribute, useEffect, useEventListener, useQuerySelector, useQuerySelectorAll, useStyle };
// src/context.ts
import { effect as effect2 } from "@preact/signals-core";
import { getEventTarget } from "@zag-js/dom-query";
import { getDocumentElement, getEventTarget } from "@zag-js/dom-query";

@@ -86,2 +86,8 @@ // src/signals.ts

};
var ContextProviderEvent = class extends Event {
constructor(key) {
super("aria-ui/context-provider", { bubbles: true, composed: true });
this.key = key;
}
};
var ContextImpl = class {

@@ -95,11 +101,39 @@ constructor(key, defaultValue) {

provide(element, signal2) {
element.addEventListener("aria-ui/context-request", (event) => {
if (element === getEventTarget(event)) {
const consumers = /* @__PURE__ */ new Map();
const handleRequest = (event) => {
const consumer = getEventTarget(event);
if (
// Don't consume the event if it's dispatched from the same element.
element === consumer || event.key !== this.key || consumers.has(event.callback) || !consumer
) {
return;
}
const { key, callback } = event;
if (key === this.key) {
callback(signal2);
event.stopPropagation();
event.stopPropagation();
event.callback(signal2);
consumers.set(event.callback, consumer);
};
const handleProvider = (event) => {
const provider = getEventTarget(event);
if (
// Don't consume the event if it's dispatched from the same element.
element === provider || event.key !== this.key || !provider
) {
return;
}
event.stopPropagation();
const previousConsumers = Array.from(consumers.entries());
consumers.clear();
for (const [callback, consumer] of previousConsumers) {
consumer.dispatchEvent(new ContextRequestEvent(this.key, callback));
}
};
element.addConnectedCallback(() => {
ensureAttachRoot(getDocumentElement(element));
element.addEventListener("aria-ui/context-request", handleRequest);
element.addEventListener("aria-ui/context-provider", handleProvider);
element.dispatchEvent(new ContextProviderEvent(this.key));
return () => {
element.removeEventListener("aria-ui/context-request", handleRequest);
element.removeEventListener("aria-ui/context-provider", handleProvider);
};
});

@@ -111,12 +145,17 @@ }

let provider;
let pending;
element.addConnectedCallback(() => {
element.dispatchEvent(
new ContextRequestEvent(this.key, (contextProvider) => {
dispose == null ? void 0 : dispose();
dispose = effect2(() => {
consumer.set(contextProvider.get());
});
provider = contextProvider;
})
);
ensureAttachRoot(getDocumentElement(element));
const onRequest = (contextProvider) => {
dispose == null ? void 0 : dispose();
dispose = effect2(() => {
consumer.set(contextProvider.get());
});
provider = contextProvider;
if (pending !== void 0) {
contextProvider.set(pending);
pending = void 0;
}
};
element.dispatchEvent(new ContextRequestEvent(this.key, onRequest));
return () => {

@@ -135,3 +174,7 @@ dispose == null ? void 0 : dispose();

const set = (value) => {
provider == null ? void 0 : provider.set(value);
if (provider) {
provider.set(value);
} else {
pending = value;
}
};

@@ -163,2 +206,70 @@ return {

}
var attachedRoots = /* @__PURE__ */ new WeakSet();
function ensureAttachRoot(root) {
if (attachedRoots.has(root)) {
return;
}
attachedRoots.add(root);
attachRoot(root);
}
function attachRoot(element) {
const store = /* @__PURE__ */ new Map();
const popPendingRequests = (key) => {
const pendingRequestData = store.get(key);
if (pendingRequestData === void 0) {
return;
}
store.delete(key);
return pendingRequestData;
};
const getPendingRequests = (key) => {
let pendingRequestData = store.get(key);
if (pendingRequestData === void 0) {
pendingRequestData = {
callbacks: /* @__PURE__ */ new WeakMap(),
requests: []
};
store.set(key, pendingRequestData);
}
return pendingRequestData;
};
const onContextProvider = (event) => {
const pendingRequestData = popPendingRequests(event.key);
if (pendingRequestData === void 0) {
return;
}
const { requests } = pendingRequestData;
for (const { elementRef, callbackRef } of requests) {
const element2 = elementRef.deref();
const callback = callbackRef.deref();
if (element2 === void 0 || callback === void 0) {
} else {
element2.dispatchEvent(new ContextRequestEvent(event.key, callback));
}
}
};
const onContextRequest = (event) => {
const element2 = getEventTarget(event);
if (!element2) {
return;
}
const callback = event.callback;
const pendingRequestData = getPendingRequests(event.key);
let callbacks = pendingRequestData.callbacks.get(element2);
if (callbacks === void 0) {
callbacks = /* @__PURE__ */ new WeakSet();
pendingRequestData.callbacks.set(element2, callbacks);
}
if (callbacks.has(callback)) {
return;
}
callbacks.add(callback);
pendingRequestData.requests.push({
elementRef: new WeakRef(element2),
callbackRef: new WeakRef(callback)
});
};
element.addEventListener("aria-ui/context-request", onContextRequest);
element.addEventListener("aria-ui/context-provider", onContextProvider);
}

@@ -255,2 +366,122 @@ // src/dom.ts

// src/event.ts
function defineEmit(element, events) {
return function emit(type, detail) {
var _a, _b, _c;
const declaration = events[type];
if (!declaration) {
throw new Error(`Event type "${String(type)}" is not defined`);
}
const bubbles = (_a = declaration.bubbles) != null ? _a : false;
const cancelable = (_b = declaration.cancelable) != null ? _b : true;
const composed = (_c = declaration.composed) != null ? _c : false;
const event = new CustomEvent(type, {
detail,
bubbles,
cancelable,
composed
});
element.dispatchEvent(event);
};
}
// src/prop.ts
import kebabCase from "just-kebab-case";
import mapValues from "just-map-values";
function getFromAttribute(prop) {
if (prop.fromAttribute) {
return prop.fromAttribute;
}
switch (typeof prop.default) {
case "string":
return (value) => {
if (value == null) {
return prop.default;
}
return String(value);
};
case "number":
return (value) => {
if (value == null) {
return prop.default;
}
return Number(value);
};
case "boolean":
return (value) => {
if (value == null) {
return prop.default;
}
return value !== "false";
};
}
}
function getToAttribute(prop) {
if (prop.toAttribute) {
return prop.toAttribute;
}
switch (typeof prop.default) {
case "string":
case "number":
case "boolean":
return String;
}
}
function getAttributeMappings(declarations) {
const attributes = [];
const attributeToProperty = /* @__PURE__ */ new Map();
const propertyToAttribute = /* @__PURE__ */ new Map();
for (const [property, declaration] of Object.entries(declarations)) {
if (declaration.attribute === false) {
continue;
}
const attribute = typeof declaration.attribute === "string" ? declaration.attribute : kebabCase(property);
attributes.push(attribute);
attributeToProperty.set(attribute, property);
propertyToAttribute.set(property, attribute);
}
return [attributes, attributeToProperty, propertyToAttribute];
}
function setupProperties(props) {
const [observedAttributes, attributeToProperty, propertyToAttribute] = getAttributeMappings(props);
const fromAttributes = mapValues(props, getFromAttribute);
const toAttributes = mapValues(props, getToAttribute);
const attributeChangedCallback = (signals, attribute, newValue) => {
const property = attributeToProperty.get(attribute);
if (!property) {
return;
}
const signal2 = signals[property];
if (!signal2) {
return;
}
const fromAttribute = fromAttributes[property];
if (!fromAttribute) {
return;
}
signal2.set(fromAttribute(newValue));
};
const useProperties = (element, signals) => {
for (const [property, attribute] of propertyToAttribute.entries()) {
const signal2 = signals[property];
if (!signal2) {
continue;
}
const toAttribute = toAttributes[property];
if (!toAttribute) {
continue;
}
useAttribute(element, attribute, () => {
var _a;
const value = signal2.get();
if (value !== ((_a = props[property]) == null ? void 0 : _a.default)) {
return toAttribute(value);
}
return null;
});
}
};
return [observedAttributes, attributeChangedCallback, useProperties];
}
// src/types.ts

@@ -261,3 +492,3 @@ var getObjectEntries = Object.entries;

// src/signal-state.ts
function mapValues(signals) {
function mapValues2(signals) {
const values = {};

@@ -276,2 +507,9 @@ for (const [key, signal2] of getObjectEntries(signals)) {

}
function getStateFromProps(props) {
const state = {};
for (const [key, prop] of getObjectEntries(props)) {
state[key] = createSignal(prop.default);
}
return state;
}

@@ -283,3 +521,3 @@ // src/element.ts

this._connectedCallbacks = [];
this._disconnectedCallback = [];
this._disconnectedCallbacks = [];
this._connected = false;

@@ -291,2 +529,3 @@ }

connectedCallback() {
if (this._connected) return;
this._connected = true;

@@ -296,3 +535,3 @@ for (const callback of this._connectedCallbacks) {

if (dispose) {
this._disconnectedCallback.push(dispose);
this._disconnectedCallbacks.push(dispose);
}

@@ -305,7 +544,8 @@ }

disconnectedCallback() {
if (!this._connected) return;
this._connected = false;
for (const callback of this._disconnectedCallback) {
for (const callback of this._disconnectedCallbacks) {
callback();
}
this._disconnectedCallback = [];
this._disconnectedCallbacks = [];
}

@@ -315,9 +555,2 @@ /**

*/
adoptedCallback() {
this.disconnectedCallback();
this.connectedCallback();
}
/**
* @hidden
*/
addConnectedCallback(callback) {

@@ -330,19 +563,30 @@ this._connectedCallbacks.push(callback);

if (dispose) {
this._disconnectedCallback.push(dispose);
this._disconnectedCallbacks.push(dispose);
}
}
};
function ElementBuilder(useElement, defaultProps) {
function defineCustomElement({
props,
events,
setup
}) {
const [observedAttributes, attributeChangedCallback, useProperties] = setupProperties(props);
class CustomElement extends BaseElement {
constructor() {
super();
this._s = mapSignals(defaultProps);
useElement(this, this._s);
this._s = getStateFromProps(props);
const emit = defineEmit(this, events);
setup(this, { state: this._s, emit });
useProperties(this, this._s);
}
attributeChangedCallback(name, oldValue, newValue) {
attributeChangedCallback(this._s, name, newValue);
}
}
defineProperties(CustomElement, defaultProps);
CustomElement.observedAttributes = observedAttributes;
defineGetterSetter(CustomElement, props);
return CustomElement;
}
function defineProperties(ElementConstructor, defaultProps) {
for (const prop of Object.keys(defaultProps)) {
function defineGetterSetter(ElementConstructor, props) {
for (const prop of Object.keys(props)) {
Object.defineProperty(ElementConstructor.prototype, prop, {

@@ -359,2 +603,8 @@ get() {

}
function registerCustomElement(name, element) {
if (typeof customElements === "undefined" || customElements.get(name)) {
return;
}
customElements.define(name, element);
}

@@ -377,3 +627,2 @@ // src/props.ts

BaseElement,
ElementBuilder,
assignProps,

@@ -384,4 +633,8 @@ batch,

createSignal,
defineCustomElement,
defineEmit,
getStateFromProps,
mapSignals,
mapValues,
mapValues2 as mapValues,
registerCustomElement,
untracked,

@@ -388,0 +641,0 @@ useAnimationFrame,

22

package.json
{
"name": "@aria-ui/core",
"type": "module",
"version": "0.0.18",
"version": "0.0.19",
"private": false,
"sideEffects": false,
"main": "dist/index.js",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js"
}
},
"files": [

@@ -12,11 +18,13 @@ "dist"

"dependencies": {
"@dddstack/ariatype-aria-attributes": "^2.0.0",
"@dddstack/ariatype-aria-roles": "^2.0.0",
"@preact/signals-core": "^1.7.0",
"@zag-js/dom-query": "^0.63.0",
"@ariatype/aria-attributes": "^1.0.1",
"@ariatype/aria-roles": "^1.0.1",
"@preact/signals-core": "^1.8.0",
"@zag-js/dom-query": "^0.74.2",
"just-kebab-case": "^4.2.0",
"just-map-values": "^3.2.0",
"server-dom-shim": "^1.0.2"
},
"devDependencies": {
"tsup": "^8.2.3",
"typescript": "^5.5.4"
"tsup": "^8.3.0",
"typescript": "^5.6.3"
},

@@ -23,0 +31,0 @@ "publishConfig": {

@@ -19,336 +19,642 @@ # @aria-ui/core

## Interfaces
## BaseElement <a id="base-element" href="#base-element">#</a>
### ReadonlySignal\<T\>
Base class for all custom elements in Aria UI. It implements the [ConnectableElement](README.md#connectable-element) interface.
A read-only signal that holds a reactive value.
<dl>
#### Type Parameters
<dt>
#### Accessors
`constructor`
##### value
</dt>
#### Methods
<dd>
##### get()
```ts
get(): T
```
new BaseElement(): BaseElement
```
Get the signal's current value.
</dd>
##### peek()
</dl>
```ts
peek(): T
```
## ConnectableElement <a id="connectable-element" href="#connectable-element">#</a>
Get the signal's current value without subscribing.
Any HTML element that has implemented the `addConnectedCallback` method.
### Signal\<T\>
<dl>
A mutable signal that can be used to manage reactive state changes.
<dt>
#### Type Parameters
`addConnectedCallback`
#### Accessors
</dt>
##### value
<dd>
#### Methods
Registers a callback to be called when the element is connected to the DOM. This callback can return a cleanup function that will be called when the element is disconnected from the DOM.
##### get()
**Type**: `(callback: () => void | VoidFunction) => void`
</dd>
</dl>
## Context <a id="context" href="#context">#</a>
A context is a way to provide and consume signals in a HTML tree.
<dl>
<dt>
`consume`
</dt>
<dd>
```ts
get(): T
const consume: (element: ConnectableElement) => Signal<T>;
```
Get the signal's current value.
</dd>
##### peek()
<dt>
`provide`
</dt>
<dd>
```ts
peek(): T
const provide: (
element: ConnectableElement,
signal: Signal<T> | ReadonlySignal<T>,
) => void;
```
Get the signal's current value without subscribing.
</dd>
##### set()
</dl>
## CustomElementOptions <a id="custom-element-options" href="#custom-element-options">#</a>
<dl>
<dt>
`events`
</dt>
<dd>
**Type**: `EventDeclarations<Events>`
</dd>
<dt>
`props`
</dt>
<dd>
**Type**: `PropDeclarations<Props>`
</dd>
<dt>
`setup`
</dt>
<dd>
**Type**: `(element: BaseElement, options: SetupOptions<Props, Events>) => void`
</dd>
</dl>
## ReadonlySignal <a id="readonly-signal" href="#readonly-signal">#</a>
A read-only signal that holds a reactive value.
<dl>
<dt>
`get value(): T`
</dt>
<dd>
**Deprecated**
</dd>
<dt>
`get`
</dt>
<dd>
```ts
set(value: T): void
const get: () => T;
```
Set the value of the signal.
</dd>
## Functions
<dt>
### ElementBuilder()
`peek`
</dt>
<dd>
```ts
function ElementBuilder<Props>(
useElement: (host: ConnectableElement, state: SignalState<Props>) => void,
defaultProps: Props,
): () => BaseElement & Props;
const peek: () => T;
```
Create a custom element class.
</dd>
## Contexts
</dl>
### Context\<T\>
## SetupOptions <a id="setup-options" href="#setup-options">#</a>
A context is a way to provide and consume signals in a HTML tree.
<dl>
#### Type Parameters
<dt>
#### Methods
`emit`
##### consume()
</dt>
```ts
consume(element: ConnectableElement): Signal<T>
```
<dd>
Receives the signal from a parent element.
**Type**: `EventEmitter<Events, keyof Events>`
##### provide()
</dd>
<dt>
`state`
</dt>
<dd>
**Type**: `SignalState<Props>`
</dd>
</dl>
## Signal <a id="signal" href="#signal">#</a>
A mutable signal that can be used to manage reactive state changes.
<dl>
<dt>
`set value(value: T)`
</dt>
<dd>
**Deprecated**
</dd>
<dt>
`get`
</dt>
<dd>
```ts
provide(element: ConnectableElement, signal: Signal<T> | ReadonlySignal<T>): void
const get: () => T;
```
Provides a signal to all children of the element.
</dd>
### createContext()
<dt>
`peek`
</dt>
<dd>
```ts
function createContext<T>(key: string | symbol, defaultValue: T): Context<T>;
const peek: () => T;
```
Creates a new context.
</dd>
## DOM
<dt>
### useAnimationFrame()
`set`
</dt>
<dd>
```ts
function useAnimationFrame(element: ConnectableElement, effect: () => void | () => void | VoidFunction): () => void
const set: (value: T) => void;
```
Executes an effect in the next animation frame.
</dd>
The given `effect` function will be called when the element is connected, and when the dependencies change afterward.
</dl>
`effect` could return a function `callback`. `callback` will be called in the next animation frame.
## TypedEventTarget <a id="typed-event-target" href="#typed-event-target">#</a>
`callback` could return a function `dispose`. `dispose` will be called when the effect is disposed.
An interface thats can be used to register event listeners.
### useAriaAttribute()
<dl>
<dt>
`addEventListener`
</dt>
<dd>
**Type**: `(type: EventType, listener: (event: DocumentEventMap[EventType]) => void) => void`
</dd>
<dt>
`removeEventListener`
</dt>
<dd>
**Type**: `(type: EventType, listener: (event: DocumentEventMap[EventType]) => void) => void`
</dd>
</dl>
## BaseElementConstructor <a id="base-element-constructor" href="#base-element-constructor">#</a>
**Type**: `new () => BaseElement & Props`
## EventDeclaration <a id="event-declaration" href="#event-declaration">#</a>
Defines options for an event.
**Type**: `{ bubbles?: boolean; cancelable?: boolean; composed?: boolean }`
## EventDeclarations <a id="event-declarations" href="#event-declarations">#</a>
Map of event types to EventDeclaration options.
**Type**: `{[EventType in keyof Required<Events>]: EventDeclaration}`
## EventEmitter <a id="event-emitter" href="#event-emitter">#</a>
**Type**: `(type: EventType extends string ? EventType : never, detail: EventType extends string ? Events[EventType]["detail"] : never) => void`
## PropDeclaration <a id="prop-declaration" href="#prop-declaration">#</a>
Defines options for a property.
**Type**: `{ attribute?: boolean | string; default: T; fromAttribute?: (value: string | null) => T; toAttribute?: (value: T) => string | null }`
## PropDeclarations <a id="prop-declarations" href="#prop-declarations">#</a>
Map of props to PropDeclaration options.
**Type**: `{[K in keyof Required<T>]: PropDeclaration<T[K]>}`
## SignalState <a id="signal-state" href="#signal-state">#</a>
A plain object containing signals.
**Type**: `{[K in keyof Required<T>]: Signal<T[K]>}`
## SignalValue <a id="signal-value" href="#signal-value">#</a>
Extracts the value type from a signal type.
**Type**: `S extends Signal<infer T> ? T : never`
## assignProps <a id="assign-props" href="#assign-props">#</a>
```ts
function useAriaAttribute<K>(
element: ConnectableElement,
key: K,
compute: () => AriaAttributes[K],
): VoidFunction;
function assignProps<T extends object>(
defaultProps: Readonly<T>,
props?: Partial<T>,
): Readonly<T>;
```
Sets the computed attribute of the element when it's connected.
Merges two objects, with the second object taking precedence. Only keys present in the first object will be included in the result.
This is a TypeScript type-safe version of [useAttribute](README.md#useattribute).
## batch <a id="batch" href="#batch">#</a>
### useAriaRole()
Groups multiple signal updates into a single batch, optimizing performance by reducing the number of updates.
This is a re-export of `batch` from `@preact/signals-core`.
```ts
function useAriaRole(element: ConnectableElement, role: AriaRole | () => AriaRole | undefined): VoidFunction
function batch<T>(fn: () => T): T;
```
Sets the `role` attribute of the element when it's connected.
Combine multiple value updates into one "commit" at the end of the provided callback.
You can pass a string or a compute function that returns a string.
Batches can be nested and changes are only flushed once the outermost batch callback completes.
### useAttribute()
Accessing a signal that has been modified within a batch will reflect its updated value.
**Returns**
The value returned by the callback.
## createComputed <a id="create-computed" href="#create-computed">#</a>
```ts
function useAttribute(
element: ConnectableElement,
key: string,
compute: () => undefined | string | number,
): VoidFunction;
function createComputed<T>(fn: () => T): ReadonlySignal<T>;
```
Sets the computed attribute of the element when it's connected.
Creates a computed signal that automatically updates its value based on the reactive dependencies it uses. Computed signals are read-only and are used to derive state from other signals, recalculating their value when dependencies change.
### useEventListener()
## createContext <a id="create-context" href="#create-context">#</a>
```ts
function useEventListener<K>(
element: ConnectableElement,
type: K,
listener: (event: HTMLElementEventMap[K]) => void,
options?: boolean | AddEventListenerOptions,
): VoidFunction;
function createContext<T>(key: string | symbol, defaultValue: T): Context<T>;
```
Registers an event listener on the element.
Creates a new context.
### useQuerySelector()
## createSignal <a id="create-signal" href="#create-signal">#</a>
```ts
function useQuerySelector<E>(
element: ConnectableElement,
selector: string,
options: MutationObserverInit,
): ReadonlySignal<E | null>;
function createSignal<T>(value: T): Signal<T>;
```
Returns the first element matching the given selector.
Creates and returns a new signal with the given initial value. Signals are reactive data sources that can be read and written to, allowing components to reactively update when their values change.
### useQuerySelectorAll()
## defineCustomElement <a id="define-custom-element" href="#define-custom-element">#</a>
```ts
function useQuerySelectorAll<E>(
element: ConnectableElement,
selector: string,
options: MutationObserverInit,
): ReadonlySignal<NodeListOf<E>>;
function defineCustomElement<
Props extends { [PropName in string | number | symbol]: unknown },
Events extends { [EventType in string | number | symbol]: CustomEvent<any> },
>(options: CustomElementOptions<Props, Events>): BaseElementConstructor<Props>;
```
Returns all elements matching the given selector.
Defines a custom element constructor.
### useStyle()
## defineEmit <a id="define-emit" href="#define-emit">#</a>
```ts
function useStyle<K>(
element: ConnectableElement,
key: K,
compute: () => CSSStyleDeclaration[K],
): VoidFunction;
function defineEmit<
Events extends { [EventType in string | number | symbol]: CustomEvent<any> },
>(
element: HTMLElement,
events: EventDeclarations<Events>,
): (type: keyof Events, detail: Events[keyof Events]["detail"]) => void;
```
Sets the computed style of the element when it's connected.
## getStateFromProps <a id="get-state-from-props" href="#get-state-from-props">#</a>
## Elements
```ts
function getStateFromProps<Props extends object>(
props: PropDeclarations<Props>,
): SignalState<Props>;
```
### BaseElement
## mapSignals <a id="map-signals" href="#map-signals">#</a>
Base class for all custom elements in Aria UI. It implements the [ConnectableElement](README.md#connectableelement) interface.
```ts
function mapSignals<T extends object>(values: T): SignalState<T>;
```
#### Constructors
Maps every value in the given object to a signal.
**Deprecated**
## mapValues <a id="map-values" href="#map-values">#</a>
```ts
new BaseElement(): BaseElement
function mapValues<T extends object>(signals: SignalState<T>): T;
```
### ConnectableElement
Maps every signal in the given object to its current value.
Any HTML element that has implemented the `addConnectedCallback` method.
**Deprecated**
#### Properties
## registerCustomElement <a id="register-custom-element" href="#register-custom-element">#</a>
| Property | Type | Description |
| --- | --- | --- |
| `addConnectedCallback` | (`callback`: () => `void` \| `VoidFunction`) => `void` | Registers a callback to be called when the element is connected to the DOM. This callback can return a cleanup function that will be called when the element is disconnected from the DOM. |
```ts
function registerCustomElement(
name: string,
element: CustomElementConstructor,
): void;
```
## Props and States
Adds the given custom element to the custom element registry.
### SignalState\<T\>
## untracked <a id="untracked" href="#untracked">#</a>
Executes a given computation without automatically tracking its dependencies, useful for avoiding unnecessary re-computations.
This is a re-export of `untracked` from `@preact/signals-core`.
```ts
type SignalState<T>: { [K in keyof T]: Signal<T[K]> };
function untracked<T>(fn: () => T): T;
```
A plain object containing signals.
Run a callback function that can access signal values without subscribing to the signal updates.
#### Type Parameters
**Returns**
### assignProps()
The value returned by the callback.
## useAnimationFrame <a id="use-animation-frame" href="#use-animation-frame">#</a>
```ts
function assignProps<T>(
defaultProps: Readonly<T>,
props?: Partial<T>,
): Readonly<T>;
function useAnimationFrame(
element: ConnectableElement,
effect: () => void | (() => void | VoidFunction),
): () => void;
```
Merges two objects, with the second object taking precedence. Only keys present in the first object will be included in the result.
Executes an effect in the next animation frame.
### mapSignals()
The given `effect` function will be called when the element is connected, and when the dependencies change afterward.
`effect` could return a function `callback`. `callback` will be called in the next animation frame.
`callback` could return a function `dispose`. `dispose` will be called when the effect is disposed.
## useAriaAttribute <a id="use-aria-attribute" href="#use-aria-attribute">#</a>
```ts
function mapSignals<T>(values: T): SignalState<T>;
function useAriaAttribute<
K extends
| "aria-dropeffect"
| "aria-grabbed"
| "aria-atomic"
| "aria-busy"
| "aria-controls"
| "aria-current"
| "aria-describedby"
| "aria-details"
| "aria-disabled"
| "aria-errormessage"
| "aria-flowto"
| "aria-haspopup"
| "aria-hidden"
| "aria-invalid"
| "aria-keyshortcuts"
| "aria-label"
| "aria-labelledby"
| "aria-live"
| "aria-owns"
| "aria-relevant"
| "aria-roledescription"
| "aria-activedescendant"
| "aria-colcount"
| "aria-colindex"
| "aria-colspan"
| "aria-description"
| "aria-posinset"
| "aria-rowcount"
| "aria-rowindex"
| "aria-rowspan"
| "aria-setsize"
| "aria-autocomplete"
| "aria-checked"
| "aria-expanded"
| "aria-level"
| "aria-modal"
| "aria-multiline"
| "aria-multiselectable"
| "aria-orientation"
| "aria-placeholder"
| "aria-pressed"
| "aria-readonly"
| "aria-required"
| "aria-selected"
| "aria-sort"
| "aria-valuemax"
| "aria-valuemin"
| "aria-valuenow"
| "aria-valuetext",
>(
element: ConnectableElement,
key: K,
compute: () => AriaAttributes[K],
): VoidFunction;
```
Maps every value in the given object to a signal.
Sets the computed attribute of the element when it's connected.
### mapValues()
This is a TypeScript type-safe version of [useAttribute](README.md#use-attribute).
## useAriaRole <a id="use-aria-role" href="#use-aria-role">#</a>
```ts
function mapValues<T>(signals: SignalState<T>): T;
function useAriaRole(
element: ConnectableElement,
role: AriaRole | (() => AriaRole | undefined),
): VoidFunction;
```
Maps every signal in the given object to its current value.
Sets the `role` attribute of the element when it's connected.
## Signals
You can pass a string or a compute function that returns a string.
### SignalValue\<S\>
## useAttribute <a id="use-attribute" href="#use-attribute">#</a>
```ts
type SignalValue<S>: S extends Signal<infer T> ? T : never;
function useAttribute(
element: ConnectableElement,
key: string,
compute: () => undefined | null | string | number,
): VoidFunction;
```
Extracts the value type from a signal type.
Sets the computed attribute of the element when it's connected.
#### Type Parameters
## useEffect <a id="use-effect" href="#use-effect">#</a>
### batch()
```ts
function batch<T>(fn: () => T): T;
function useEffect(
element: ConnectableElement,
callback: () => void | VoidFunction,
): () => void;
```
Combine multiple value updates into one "commit" at the end of the provided callback.
Registers a callback to be called when the given element is connected to the DOM. It will track which signals are accessed and re-run their callback when those signals change. The callback can return a cleanup function that will be called when the effect is destroyed.
Batches can be nested and changes are only flushed once the outermost batch callback completes.
The effect will be destroyed and all signals it was subscribed to will be unsubscribed from, when the element is disconnected from the DOM. You can also manually destroy the effect by calling the returned function.
Accessing a signal that has been modified within a batch will reflect its updated value.
## useEventListener <a id="use-event-listener" href="#use-event-listener">#</a>
### createComputed()
```ts
function createComputed<T>(fn: () => T): ReadonlySignal<T>;
function useEventListener<K extends keyof HTMLElementEventMap>(
element: ConnectableElement,
type: K,
listener: (event: HTMLElementEventMap[K]) => void,
options?: boolean | AddEventListenerOptions,
): VoidFunction;
```
Creates a computed signal that automatically updates its value based on the reactive dependencies it uses. Computed signals are read-only and are used to derive state from other signals, recalculating their value when dependencies change.
Registers an event listener on the element.
### createSignal()
## useQuerySelector <a id="use-query-selector" href="#use-query-selector">#</a>
```ts
function createSignal<T>(value: T): Signal<T>;
function useQuerySelector<E extends Element>(
element: ConnectableElement,
selector: string,
options?: MutationObserverInit,
): ReadonlySignal<E | null>;
```
Creates and returns a new signal with the given initial value. Signals are reactive data sources that can be read and written to, allowing components to reactively update when their values change.
Returns the first element matching the given selector.
### untracked()
## useQuerySelectorAll <a id="use-query-selector-all" href="#use-query-selector-all">#</a>
```ts
function untracked<T>(fn: () => T): T;
function useQuerySelectorAll<E extends Element>(
element: ConnectableElement,
selector: string,
options?: MutationObserverInit,
): ReadonlySignal<NodeListOf<E>>;
```
Run a callback function that can access signal values without subscribing to the signal updates.
Returns all elements matching the given selector.
### useEffect()
## useStyle <a id="use-style" href="#use-style">#</a>
```ts
function useEffect(
function useStyle<K extends keyof CSSStyleDeclaration>(
element: ConnectableElement,
callback: () => void | VoidFunction,
): () => void;
key: K,
compute: () => CSSStyleDeclaration[K],
): VoidFunction;
```
Registers a callback to be called when the given element is connected to the DOM. It will track which signals are accessed and re-run their callback when those signals change. The callback can return a cleanup function that will be called when the effect is destroyed.
The effect will be destroyed and all signals it was subscribed to will be unsubscribed from, when the element is disconnected from the DOM. You can also manually destroy the effect by calling the returned function.
Sets the computed style of the element when it's connected.
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc